home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 4 / ETO Development Tools 4.iso / Tools - Objects / MacApp / MacApp 3.0a2 / Libraries / UGridView.cp < prev    next >
Text File  |  1991-05-01  |  81KB  |  2,946 lines

  1. // UGridView.cp 
  2. // Copyright © 1987-1991 by Apple Computer Inc. All rights reserved.
  3.  
  4. #ifndef __UGRIDVIEW__
  5. #include <UGridView.h>
  6. #endif
  7.  
  8. #ifndef __STDIO__
  9. #include <StdIo.h>
  10. #endif
  11.  
  12. #ifndef __UGEOMETRY__
  13. #include <UGeometry.h>
  14. #endif
  15.  
  16. #ifndef __ERRORS__
  17. #include <Errors.h>
  18. #endif
  19.  
  20. #ifndef __TOOLUTILS__
  21. #include <ToolUtils.h>
  22. #endif
  23.  
  24. #ifndef __PACKAGES__
  25. #include <Packages.h>
  26. #endif
  27.  
  28. #ifndef __STDLIB__
  29. #include <StdLib.h>
  30. #endif
  31.  
  32. #ifndef __UADORNERS__
  33. #include <UAdorners.h>
  34. #endif
  35.  
  36. #ifndef __UMACAPPUTILITIES__
  37. #include <UMacAppUtilities.h>
  38. #endif
  39.  
  40. #ifndef __UMEMORY__
  41. #include <UMemory.h>
  42. #endif
  43.  
  44. #ifndef __UMACAPPGLOBALS__
  45. #include <UMacAppGlobals.h>
  46. #endif
  47.  
  48.  
  49. //--------------------------------------------------------------------------------------------------
  50. RgnHandle pPixelsToHighlight;
  51. RgnHandle pPreviousSelection;
  52. RgnHandle pDifference;
  53. RgnHandle pVisibleCells;
  54. RgnHandle pInvalidateRgn;
  55.  
  56. //--------------------------------------------------------------------------------------------------
  57. #pragma segment GVInit
  58.  
  59. pascal void InitUGridView(void)
  60. {
  61.     if (qTemplateViews)
  62.     {
  63.         // So the linker doesn't dead strip these 
  64.         if (gDeadStripSuppression)
  65.         {
  66.             DontDeadStrip(TGridView);
  67.             DontDeadStrip(TTextGridView);
  68.             DontDeadStrip(TTextListView);
  69.         }
  70.  
  71.         RegisterStdType("TGridView", kStdGridView);
  72.         RegisterStdType("TTextGridView", kStdTextGridView);
  73.         RegisterStdType("TTextListView", kStdTextListView);
  74.     }
  75.  
  76.     pPixelsToHighlight = MakeNewRgn();
  77.     pPreviousSelection = MakeNewRgn();
  78.     pDifference = MakeNewRgn();
  79.     pVisibleCells = MakeNewRgn();
  80.     pInvalidateRgn = MakeNewRgn();
  81.     gUGridViewInitialized = TRUE;
  82. }
  83.  
  84. //--------------------------------------------------------------------------------------------------
  85. #pragma segment GVOpen
  86. pascal void TRunArray::Initialize(void)            // override 
  87. {
  88.     inherited::Initialize();
  89.  
  90.     fChunks = NULL;
  91.     fLastChunk = 0;
  92.     fLastIndex = 1;
  93.     fLastItem = 0;
  94.     fLastTotal = 0;
  95.     fNoOfChunks = 0;
  96.     fNoOfItems = 0;
  97.     fTotal = 0;
  98. }
  99.  
  100. //--------------------------------------------------------------------------------------------------
  101. #pragma segment GVOpen
  102.  
  103. pascal void TRunArray::IRunArray(void)
  104. {
  105.     this->IObject();
  106.     fChunks = (ChunkArrayHandle)(NewPermHandle(0));
  107. }
  108.  
  109. //--------------------------------------------------------------------------------------------------
  110. #pragma segment GVClose
  111.  
  112. pascal void TRunArray::Free(void)                // override 
  113. {
  114.     fChunks = (ChunkArrayHandle)DisposeIfHandle((Handle)fChunks);// Blow chunks 
  115.  
  116.     inherited::Free();
  117. }
  118.  
  119. //--------------------------------------------------------------------------------------------------
  120. #pragma segment GVNonRes
  121.  
  122. pascal void TRunArray::DeleteItems(short firstItem,
  123.                                    short noOfItems)
  124. {
  125.     long offset;
  126.     long result;
  127.     short i;
  128.     short num;
  129.     long theTotal;
  130.     short index;
  131.  
  132.     if (!FindChunk(firstItem, num, index, theTotal))
  133.     {
  134. #if qDebug
  135.         Str255 theString;
  136.         ConcatNumber("Unable to find chunk for item ", firstItem, theString);
  137.         ProgramBreak(theString);
  138. #endif
  139.         return;
  140.     }
  141.  
  142.     for (i = 1; i <= noOfItems; ++i)
  143.     {
  144.         fTotal -= (*fChunks)[num].value;
  145.  
  146.         --(*fChunks)[num].count;
  147.  
  148.         if ((*fChunks)[num].count < index)
  149.         {
  150.             if ((*fChunks)[num].count == 0)
  151.             {
  152.                 // need to delete that chunk 
  153.                 offset = IntMultiply(num, sizeof(RunArrayChunk));
  154.                 result = Munger((Handle)fChunks, offset, NULL, sizeof(RunArrayChunk), (Ptr) & result, 0);
  155.                 FailMemError();
  156.                 --fNoOfChunks;
  157.  
  158.                 // Thanks JDR 10/28/89 
  159.                 // see if we can consolidate chunks 
  160.                 if ((num > 0) && (num < fNoOfChunks) && ((*fChunks)[num - 1].value == (*fChunks)[num].value))
  161.                 {
  162.                     index = (*fChunks)[num - 1].count + 1;
  163.                     (*fChunks)[num - 1].count += (*fChunks)[num].count;
  164.                     // need to delete that chunk 
  165.                     result = Munger((Handle)fChunks, offset, NULL, sizeof(RunArrayChunk), (Ptr) & result, 0);
  166.                     FailMemError();
  167.                     --num;
  168.                     --fNoOfChunks;
  169.                 }
  170.             }
  171.             else
  172.                 ++num;
  173.             index = 1;
  174.         }
  175.     }
  176.  
  177.     fNoOfItems -= noOfItems;
  178.  
  179.     // reset the cache 
  180.     fLastItem = 0;
  181.     fLastChunk = 0;
  182.     fLastTotal = 0;
  183.     fLastIndex = 1;
  184. }
  185.  
  186. //--------------------------------------------------------------------------------------------------
  187. #pragma segment GVFields
  188.  
  189. pascal void TRunArray::Fields(TObject* obj)        // override 
  190. {
  191.     Str255 aString;
  192.     Str255 numString;
  193.  
  194.     obj->DoToField("TRunArray", NULL, bClass);
  195.     obj->DoToField("fNoOfItems", &fNoOfItems, bInteger);
  196.     obj->DoToField("fNoOfChunks", &fNoOfChunks, bInteger);
  197.     obj->DoToField("fTotal", &fTotal, bLongInt);
  198.     obj->DoToField("fLastItem", &fLastItem, bInteger);
  199.     obj->DoToField("fLastChunk", &fLastChunk, bInteger);
  200.     obj->DoToField("fLastTotal", &fLastTotal, bLongInt);
  201.     obj->DoToField("fLastIndex", &fLastIndex, bInteger);
  202.  
  203.     // !!! When these come from the dynamic area remember to put the field in the DynamicField method 
  204.     for (short i = 0; i <= fNoOfChunks; ++i)
  205.     {
  206.         NumToString(i, numString);
  207.         aString = "count[" + numString + "]";
  208.         obj->DoToField(aString, &(*fChunks)[i].count, bInteger);
  209.         aString = "value[" + numString + "]";
  210.         obj->DoToField(aString, &(*fChunks)[i].value, bInteger);
  211.     }
  212.     inherited::Fields(obj);
  213. }
  214.  
  215. //--------------------------------------------------------------------------------------------------
  216. #pragma segment GVRes
  217.  
  218. pascal Boolean TRunArray::FindChunk(short item,
  219.                                     short& chunk,
  220.                                     short& indexInChunk,
  221.                                     long& theTotal)
  222. {
  223.     short thisItem;
  224.     short count;
  225.     short delta;
  226.     Boolean result;
  227.  
  228.     if ((fNoOfChunks <= 0) || (item > fNoOfItems) || (item <= 0))
  229.     {
  230.         chunk = 0;
  231.         theTotal = 0;
  232.         indexInChunk = 0;
  233.         result = FALSE;
  234.         item = 0;
  235.     }
  236.     else if (item == fLastItem)
  237.     {
  238.         // check for the very easy case 
  239.         chunk = fLastChunk;
  240.         theTotal = fLastTotal;
  241.         indexInChunk = fLastIndex;
  242.         result = TRUE;
  243.     }
  244.     else
  245.     {
  246.         delta = abs(item - fLastItem);
  247.  
  248.         if ((delta >= item) || (item <= (*fChunks)[0].count))
  249.         {
  250.             // start from the first chunk 
  251.             chunk = 0;
  252.             theTotal = 0;
  253.             thisItem = 0;
  254.         }
  255.         else if (delta > (fNoOfItems - item + 1))
  256.         {
  257.             // start from the end chunk 
  258.             chunk = fNoOfChunks - 1;
  259.             count = (*fChunks)[chunk].count;
  260.             theTotal = fTotal - IntMultiply(count, (*fChunks)[chunk].value);
  261.             thisItem = fNoOfItems - count;
  262.         }
  263.         else
  264.         {                                        // start from the previous values 
  265.             chunk = fLastChunk;
  266.             theTotal = fLastTotal;
  267.             thisItem = fLastItem - fLastIndex;
  268.         }
  269.  
  270.         if (item > thisItem)
  271.         {
  272.             while ((thisItem + (*fChunks)[chunk].count) < item)
  273.             {
  274.                 count = (*fChunks)[chunk].count;
  275.                 theTotal += IntMultiply(count, (*fChunks)[chunk].value);
  276.                 thisItem += count;
  277.                 ++chunk;
  278.             }
  279.         }
  280.         else
  281.         {
  282.             do
  283.             {
  284.                 --chunk;
  285.                 count = (*fChunks)[chunk].count;
  286.                 theTotal -= IntMultiply(count, (*fChunks)[chunk].value);
  287.                 thisItem -= count;
  288.             } while (thisItem >= item);
  289.         }
  290.         indexInChunk = item - thisItem;
  291.         result = TRUE;
  292.     }
  293.     // cache the last values 
  294.     fLastItem = item;
  295.     fLastChunk = chunk;
  296.     fLastTotal = theTotal;
  297.     fLastIndex = indexInChunk;
  298.  
  299.     return result;
  300. }
  301.  
  302. //--------------------------------------------------------------------------------------------------
  303. #pragma segment GVRes
  304.  
  305. pascal short TRunArray::FindItem(long theTotal)
  306. {
  307.     short result = 0;
  308.     if ((theTotal >= 0) && (theTotal <= fTotal) && (fNoOfChunks > 0))
  309.         if (fNoOfChunks == 1)
  310.         {
  311.             if ((*fChunks)[0].value > 0)
  312.                 result = (short)Min(((theTotal - 1) / (*fChunks)[0].value) + 1, fNoOfItems);//!!! Cast
  313.         }
  314.         else if (theTotal == 0)
  315.             result = 1;
  316.         else
  317.         {
  318.             ++theTotal;
  319.             short runningCount = 0;
  320.             for (short i = 0; i <= fNoOfChunks - 1; ++i)
  321.             {
  322.                 RunArrayChunk chunk = (*fChunks)[i];
  323.  
  324.                 theTotal -= IntMultiply(chunk.value, chunk.count);
  325.                 runningCount += chunk.count;
  326.                 if (theTotal <= 0)
  327.                 {
  328.                     result = (short)(runningCount + (theTotal / chunk.value));//!!! Cast
  329.                     return result;
  330.                 }
  331.             }
  332.             result = fNoOfItems;
  333.         }
  334.     return result;
  335. }
  336.  
  337. //--------------------------------------------------------------------------------------------------
  338. #pragma segment GVRes
  339.  
  340. pascal short TRunArray::GetValue(short item)
  341. {
  342.     short num;
  343.     long theTotal;
  344.     short index;
  345.  
  346.     if (fNoOfChunks == 1)
  347.         return (*fChunks)[0].value;
  348.     else if (this->FindChunk(item, num, index, theTotal))
  349.         return (*fChunks)[num].value;
  350.     else
  351.         return 0;
  352. }
  353.  
  354. //--------------------------------------------------------------------------------------------------
  355. #pragma segment GVRes
  356.  
  357. pascal void TRunArray::InsertItems(short firstItem,
  358.                                    short noOfItems,
  359.                                    short value)
  360. {
  361.     short num;
  362.     long theTotal;
  363.     short index;
  364.     long oldSize;
  365.     long result;
  366.     struct
  367.     {
  368.         RunArrayChunk chunk1;
  369.         RunArrayChunk chunk2;
  370.     } tempChunks;
  371.  
  372.  
  373.     // Check if we can just increment the last size count 
  374.  
  375.     if ((firstItem > fNoOfItems) && (fNoOfChunks > 0) && ((*fChunks)[fNoOfChunks - 1].value == value))
  376.         (*fChunks)[fNoOfChunks - 1].count += noOfItems;
  377.  
  378.     // check if we can increment any size count 
  379.     else if (this->FindChunk(firstItem, num, index, theTotal) && ((*fChunks)[num].value == value))
  380.  
  381.         (*fChunks)[num].count += noOfItems;
  382.  
  383.     // check if this would actually fit as the last item in the previous chunk 
  384.     // Thanks Martin Frické, 10/31/89
  385.  
  386.     else if ((num > 0) && (index == 1) && ((*fChunks)[num - 1].value == value))
  387.         (*fChunks)[num - 1].count += noOfItems;
  388.  
  389.     // We need to create a new chunk, possibly two 
  390.     else
  391.     {
  392.         oldSize = GetHandleSize((Handle)fChunks);
  393.         tempChunks.chunk1.value = value;
  394.         tempChunks.chunk1.count = noOfItems;
  395.  
  396.         if ((index <= 1) || (firstItem > fNoOfItems))
  397.         {
  398.             // need to add one chunk 
  399.             if (firstItem > fNoOfItems)
  400.                 num = fNoOfChunks;                // add a row on the end 
  401.  
  402.             result = Munger((Handle)fChunks, IntMultiply(num, sizeof(RunArrayChunk)), NULL, 0, (Ptr) & tempChunks, sizeof(RunArrayChunk));
  403.             FailMemError();
  404.             ++fNoOfChunks;
  405.         }
  406.         else
  407.         {
  408.             // need to add two 
  409.             tempChunks.chunk2.count = (*fChunks)[num].count - index + 1;
  410.             tempChunks.chunk2.value = (*fChunks)[num].value;
  411.             (*fChunks)[num].count = index - 1;
  412.             result = Munger((Handle)fChunks, IntMultiply(num + 1, sizeof(RunArrayChunk)), NULL, 0, (Ptr) & tempChunks, 2 * sizeof(RunArrayChunk));
  413.             FailMemError();
  414.             fNoOfChunks += 2;
  415.         }
  416.         if (GetHandleSize((Handle)fChunks) <= oldSize)
  417.             Failure(memFullErr, 0);
  418.     }
  419.  
  420.     // reset the cache 
  421.     fLastItem = 0;
  422.     fLastChunk = 0;
  423.     fLastTotal = 0;
  424.     fLastIndex = 1;
  425.  
  426.     fNoOfItems += noOfItems;
  427.     fTotal += IntMultiply(noOfItems, value);
  428. }
  429.  
  430. //--------------------------------------------------------------------------------------------------
  431. #pragma segment GVRes
  432.  
  433. pascal long TRunArray::SumValues(short firstItem,
  434.                                  short noOfItems)
  435. {
  436.     short chunk;
  437.     short indexInChunk;
  438.     long total;
  439.     long precedingTotal;
  440.     long result;
  441.  
  442.     result = 0;
  443.  
  444.     if (fNoOfChunks == 1)
  445.         result = IntMultiply(noOfItems, (*fChunks)[0].value);
  446.     else if (firstItem == 1)
  447.     {
  448.         if (this->FindChunk(noOfItems, chunk, indexInChunk, total))
  449.             result = total + IntMultiply(indexInChunk, (*fChunks)[chunk].value);
  450.     }
  451.     else if (this->FindChunk(firstItem, chunk, indexInChunk, total))
  452.     {
  453.         precedingTotal = total + IntMultiply(indexInChunk - 1, (*fChunks)[chunk].value);
  454.         if (this->FindChunk(firstItem + noOfItems - 1, chunk, indexInChunk, total))
  455.             result = total + IntMultiply(indexInChunk, (*fChunks)[chunk].value) - precedingTotal;
  456.     }
  457.     return result;
  458. }
  459.  
  460. //--------------------------------------------------------------------------------------------------
  461. #pragma segment GVOpen
  462.  
  463. pascal void TGridView::Initialize(void)            // override 
  464. {
  465.     inherited::Initialize();
  466. #if qDebug
  467.     if (!gUGridViewInitialized)
  468.     {
  469.         ProgramBreak("InitUGridView must be called before creating a grid view.");
  470.         Failure(noErr, 0);
  471.     }
  472. #endif
  473.  
  474.     fNumOfRows = 0;
  475.     fNumOfCols = 0;
  476.  
  477.     fAdornRows = FALSE;
  478.     fAdornCols = FALSE;
  479.     fRowInset = 0;
  480.     fColInset = 0;
  481.     fColWidths = NULL;
  482.     fRowHeights = NULL;
  483.  
  484.     fSelections = NULL;
  485.     fHLRegion = NULL;
  486.     fTempSelections = NULL;
  487.  
  488.     fSingleSelection = TRUE;
  489. }
  490.  
  491. //--------------------------------------------------------------------------------------------------
  492. #pragma segment GVOpen
  493.  
  494. pascal void TGridView::IGridView(TDocument* itsDocument,
  495.                                  // Its document 
  496.                                  TView* itsSuperView,
  497.                                  // Its parent view 
  498.                                  const VPoint& itsLocation,
  499.                                  // Top, Left in parent's coords 
  500.                                  const VPoint& itsSize,
  501.                                  // Ignored for SizeVariable
  502.                                  SizeDeterminer itsHSizeDet,
  503.                                  SizeDeterminer itsVSizeDet,
  504.                                  // Size determiners 
  505.                                  short numOfRows,
  506.                                  // Number of rows initially 
  507.                                  short numOfCols,
  508.                                  // Number of columns initially 
  509.                                  short rowHeight,
  510.                                  // Height of initial rows 
  511.                                  short colWidth,
  512.                                  // Height of initial columns 
  513.                                  Boolean adornRows,
  514.                                  // Adornment for Rows? 
  515.                                  Boolean adornCols,
  516.                                  // Adornment for Columns? 
  517.                                  short rowInset,
  518.                                  // horizontal space between cells 
  519.                                  short colInset,
  520.                                  // vertical space between cells 
  521.                                  Boolean singleSelection)// single cell selection? 
  522.  
  523. {
  524.     FailInfo fi;
  525.  
  526.     fSelections = NULL;
  527.     fHLRegion = NULL;
  528.     fTempSelections = NULL;
  529.     fColWidths = NULL;
  530.     fRowHeights = NULL;
  531.  
  532. #if qDebug
  533.     if (!gUGridViewInitialized)
  534.     {
  535.         ProgramBreak("InitUGridView must be called before creating a grid view.");
  536.         Failure(noErr, 0);
  537.     }
  538. #endif
  539.  
  540.     this->IView(itsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet);
  541.  
  542.     fAdornRows = adornRows;
  543.     fAdornCols = adornCols;
  544.  
  545.     // Make sure the insets are evenly divided between top/bottom or left/right 
  546.     if (rowInset & 1)                            //    (ODD(rowInset))
  547.         fRowInset = rowInset + 1;
  548.     else
  549.         fRowInset = rowInset;
  550.  
  551.     if (colInset & 1)                            //    (ODD(colInset))
  552.         fColInset = colInset + 1;
  553.     else
  554.         fColInset = colInset;
  555.  
  556.     if (fi.Try())
  557.     {
  558.  
  559.         fColWidths = new TRunArray;
  560.         fColWidths->IRunArray();
  561.  
  562.         fRowHeights = new TRunArray;
  563.         fRowHeights->IRunArray();
  564.  
  565.         fSelections = MakeNewRgn();                // region to hold current selections 
  566.         fHLRegion = MakeNewRgn();                // region to hold current highlighted cells 
  567.         fTempSelections = MakeNewRgn();            // used by SetSelectionRect 
  568.  
  569.         fSingleSelection = singleSelection;
  570.  
  571.         if (numOfCols > 0)
  572.             this->InsColFirst(numOfCols, colWidth);
  573.         if (numOfRows > 0)
  574.             this->InsRowFirst(numOfRows, rowHeight);
  575.  
  576.         fi.Success();
  577.     }
  578.     else    // Recover
  579.     {
  580.         this->Free();
  581.         fi.ReSignal();
  582.     }
  583.  
  584.     this->AddAdorner(gSelectionAdorner, kViewAdornPriority, FALSE);    // wants DoHighlightSelection 
  585. }
  586.  
  587.  
  588. //--------------------------------------------------------------------------------------------------
  589. #pragma segment GVOpen
  590.  
  591. pascal void TGridView::IRes(TDocument* itsDocument,
  592.                             TView* itsSuperView,
  593.                             Ptr& itsParams)        // override 
  594. {
  595.     FailInfo fi;
  596.  
  597.     fSelections = NULL;
  598.     fHLRegion = NULL;
  599.     fTempSelections = NULL;
  600.     fColWidths = NULL;
  601.     fRowHeights = NULL;
  602.  
  603. #if qDebug
  604.     if (!gUGridViewInitialized)
  605.     {
  606.         ProgramBreak("InitUGridView must be called before creating a grid view.");
  607.         Failure(noErr, 0);
  608.     }
  609. #endif
  610.  
  611.     inherited::IRes(itsDocument, itsSuperView, itsParams);
  612.  
  613.     GridViewTemplate& templateData = *((GridViewTemplate *) itsParams);
  614.  
  615.     fNumOfRows = 0;
  616.     fNumOfCols = 0;
  617.  
  618.     fAdornRows = templateData.adornRows;
  619.     fAdornCols = templateData.adornCols;
  620.  
  621.     // Make sure the insets are evenly divided between top/bottom or left/right 
  622.     if (templateData.rowInset & 1)                //    (ODD(templateData.rowInset))
  623.         fRowInset = templateData.rowInset + 1;
  624.     else
  625.         fRowInset = templateData.rowInset;
  626.  
  627.     if (templateData.colInset & 1)                //  (ODD(templateData.colInset))
  628.         fColInset = templateData.colInset + 1;
  629.     else
  630.         fColInset = templateData.colInset;
  631.  
  632.     fSingleSelection = templateData.singleSelection;
  633.  
  634.     if (fi.Try())
  635.     {
  636.  
  637.         fColWidths = new TRunArray;
  638.         fColWidths->IRunArray();
  639.  
  640.         fRowHeights = new TRunArray;
  641.         fRowHeights->IRunArray();
  642.  
  643.         fSelections = MakeNewRgn();                // region to hold current selections 
  644.         fHLRegion = MakeNewRgn();                // region to hold current highlighted cells 
  645.         fTempSelections = MakeNewRgn();            // used by SetSelectionRect 
  646.  
  647.         if (templateData.numOfCols > 0)
  648.             this->InsColFirst(templateData.numOfCols, templateData.colWidth);
  649.         if (templateData.numOfRows > 0)
  650.             this->InsRowFirst(templateData.numOfRows, templateData.rowHeight);
  651.  
  652.         fi.Success();
  653.     }
  654.     else    // Recover
  655.     {
  656.         this->Free();
  657.         fi.ReSignal();
  658.     }
  659.  
  660.  
  661.     OffsetPtr(itsParams, sizeof(GridViewTemplate));
  662.  
  663.     this->AddAdorner(gSelectionAdorner, kViewAdornPriority, FALSE);    // wants DoHighlightSelection 
  664. }
  665.  
  666. //--------------------------------------------------------------------------------------------------
  667. #pragma segment GVRes
  668.  
  669. pascal TObject* TGridView::Clone(void)            // override 
  670. {
  671.     TGridView * aClonedGridView;
  672.     FailInfo fi;
  673.  
  674.     VOLATILE(aClonedGridView);
  675.  
  676.     aClonedGridView = (TGridView *)(inherited::Clone());
  677.  
  678.     aClonedGridView->fNumOfCols = 0;
  679.     aClonedGridView->fNumOfRows = 0;
  680.  
  681.     // This code is neccessary becuase MacApp does not support cloning properly
  682.     // It could be replaced with TGridView(inputView).fColWidths.Clone otherwise
  683.  
  684.     if (fi.Try())
  685.     {
  686.         aClonedGridView->fColWidths = new TRunArray;
  687.         aClonedGridView->fColWidths->IRunArray();
  688.  
  689.         aClonedGridView->fRowHeights = new TRunArray;
  690.         aClonedGridView->fRowHeights->IRunArray();
  691.  
  692.         aClonedGridView->fSelections = MakeNewRgn();// region to hold current selections 
  693.         aClonedGridView->fHLRegion = MakeNewRgn();// region to hold current highlighted cells 
  694.         aClonedGridView->fTempSelections = MakeNewRgn();// used by SetSelectionRect 
  695.  
  696.         fi.Success();
  697.     }
  698.     else    // Recover
  699.     {
  700.         aClonedGridView->Free();
  701.         fi.ReSignal();
  702.     }
  703.  
  704.     if (fNumOfCols > 0)
  705.         aClonedGridView->InsColFirst(fNumOfCols, this->GetColWidth(1));
  706.     if (fNumOfRows > 0)
  707.         aClonedGridView->InsRowFirst(fNumOfRows, this->GetRowHeight(1));
  708.  
  709.  
  710.     return aClonedGridView;
  711. }
  712.  
  713. //--------------------------------------------------------------------------------------------------
  714. #pragma segment GVNonRes
  715.  
  716. pascal void TGridView::WRes(ViewRsrcHandle theResource,
  717.                             Ptr& itsParams)        // override 
  718. {
  719.     inherited::WRes(theResource, itsParams);
  720.  
  721.     GridViewTemplate& templateData = *((GridViewTemplate *) ExpandPtr((Handle)theResource, itsParams, sizeof(GridViewTemplate)));
  722.  
  723.     templateData.numOfRows = fNumOfRows;
  724.     templateData.numOfCols = fNumOfCols;
  725.     if (fNumOfRows > 0)
  726.         templateData.rowHeight = this->GetRowHeight(1);
  727.     else
  728.         templateData.rowHeight = 0;
  729.     if (fNumOfCols > 0)
  730.         templateData.colWidth = this->GetColWidth(1);
  731.     else
  732.         templateData.colWidth = 0;
  733.     templateData.rowInset = fRowInset;
  734.     templateData.colInset = fColInset;
  735.     templateData.adornRows = fAdornRows;
  736.     templateData.adornCols = fAdornCols;
  737.     templateData.singleSelection = fSingleSelection;
  738. }
  739.  
  740. //--------------------------------------------------------------------------------------------------
  741. #pragma segment GVNonRes
  742.  
  743. pascal void TGridView::WriteRes(ViewRsrcHandle theResource,
  744.                                 Ptr& itsParams)    // override 
  745. {
  746.     gWResSignature = 'grid';
  747.     gWResType = "TGridView";
  748.     this->WRes(theResource, itsParams);
  749. }
  750.  
  751. //--------------------------------------------------------------------------------------------------
  752. #pragma segment GVClose
  753.  
  754. pascal void TGridView::Free(void)                // override 
  755. {
  756.     // Dispose regions 
  757.     fSelections = DisposeIfRgnHandle(fSelections);
  758.     fHLRegion = DisposeIfRgnHandle(fHLRegion);
  759.     fTempSelections = DisposeIfRgnHandle(fTempSelections);
  760.  
  761.     fColWidths = (TRunArray *)(FreeIfObject(fColWidths));
  762.     fRowHeights = (TRunArray *)(FreeIfObject(fRowHeights));
  763.  
  764.     inherited::Free();
  765. }
  766.  
  767. //--------------------------------------------------------------------------------------------------
  768. #pragma segment GVRes
  769.  
  770. pascal void TGridView::AllCellsDo(DoToCellType DoToCell,
  771.                                   void* staticLink)
  772. {
  773.     Rect bounds(1, 1, fNumOfRows, fNumOfCols);
  774.     this->EachCellDo(bounds[topLeft], bounds[botRight], DoToCell, staticLink);
  775. }
  776.  
  777. //--------------------------------------------------------------------------------------------------
  778. #pragma segment GVRes
  779.  
  780. pascal void TGridView::AdornCol(short aCol,
  781.                                 const VRect& area)
  782. {
  783.     Rect qdRect;
  784.  
  785.     PenNormal();
  786.     this->ViewToQDRect(area, qdRect);
  787.  
  788.     MoveTo(qdRect.right, qdRect.top);
  789.     Line(0, qdRect.Length(vSel));
  790.     if (aCol == 1)
  791.     {
  792.         MoveTo(qdRect.left, qdRect.top);
  793.         Line(0, qdRect.Length(vSel));
  794.     }
  795. }
  796.  
  797. //--------------------------------------------------------------------------------------------------
  798. #pragma segment GVRes
  799.  
  800. pascal void TGridView::AdornRow(short aRow,
  801.                                 const VRect& area)
  802. {
  803.     Rect qdRect;
  804.  
  805.     PenNormal();
  806.     this->ViewToQDRect(area, qdRect);
  807.  
  808.     MoveTo(qdRect.left, qdRect.bottom);
  809.     Line(qdRect.Length(hSel), 0);
  810.     if (aRow == 1)
  811.     {
  812.         MoveTo(qdRect.left, qdRect.top);
  813.         Line(qdRect.Length(hSel), 0);
  814.     }
  815. }
  816.  
  817. //--------------------------------------------------------------------------------------------------
  818. #pragma segment GVRes
  819.  
  820. pascal void TGridView::CalcMinSize(VPoint& minSize)// override 
  821. {
  822.     inherited::CalcMinSize(minSize);
  823.  
  824.     // Set the amount of room needed for that many items 
  825.     minSize = VPoint(fRowHeights->fTotal, fColWidths->fTotal);
  826. }
  827.  
  828. //--------------------------------------------------------------------------------------------------
  829. #pragma segment GVRes
  830.  
  831. pascal Boolean TGridView::CanSelectCell(GridCell aCell)
  832. {
  833.     return ((aCell.h >= 1) && (aCell.v >= 1) && (aCell.h <= fNumOfCols) && (aCell.v <= fNumOfRows));
  834. }
  835.  
  836. //--------------------------------------------------------------------------------------------------
  837. #pragma segment GVRes
  838.  
  839. pascal void TGridView::CellToVRect(GridCell aCell,
  840.                                    VRect& aRect)
  841. {
  842.     short width;
  843.     short height;
  844.  
  845.     if ((aCell.h < 1) || (aCell.v < 1) || (aCell.h > fNumOfCols) || (aCell.v > fNumOfRows))
  846.     {
  847. #if qRangeCheck && qDebugMsg
  848.         fprintf(stderr, "aCell.h == %6d fNumOfCols == %6d", aCell.h, fNumOfCols);
  849.         fprintf(stderr, "aCell.v == %6d fNumOfCols == %6d", aCell.v, fNumOfCols);
  850.         ProgramBreak("Range Check in CellToVRect");
  851. #endif
  852.  
  853.         aRect = gZeroVRect;
  854.     }
  855.     else                                        // all the params look OK 
  856.         {
  857.         width = fColWidths->GetValue(aCell.h);
  858.         if (fColWidths->fNoOfChunks == 1)
  859.             aRect.left = IntMultiply(width, aCell.h - 1);
  860.         else
  861.             aRect.left = fColWidths->SumValues(1, aCell.h - 1);
  862.         aRect.right = aRect.left + width;
  863.  
  864.         height = fRowHeights->GetValue(aCell.v);
  865.         if (fRowHeights->fNoOfChunks == 1)
  866.             aRect.top = IntMultiply(height, aCell.v - 1);
  867.         else
  868.             aRect.top = fRowHeights->SumValues(1, aCell.v - 1);
  869.         aRect.bottom = aRect.top + height;
  870.     }
  871. }
  872.  
  873. //--------------------------------------------------------------------------------------------------
  874. #pragma segment GVRes
  875.  
  876. pascal void TGridView::ColToVRect(short aCol,
  877.                                   short numOfCols,
  878.                                   VRect& aRect)
  879. {
  880.     long width;
  881.     long leftEdge;
  882.  
  883.     if ((aCol < 1) || (numOfCols < 1) || (aCol + numOfCols - 1 > fNumOfCols))
  884.     {
  885. #if qDebugMsg && qRangeCheck
  886.         fprintf(stderr, "fNumOfCols == %1d aCol == %1d", fNumOfCols, aCol);
  887.         ProgramBreak("Range Check in ColToVRect");
  888. #endif
  889.  
  890.         aRect = gZeroVRect;
  891.     }
  892.     else                                        // all the params look OK 
  893.         {
  894.         if (fColWidths->fNoOfChunks == 1)        // only one column height 
  895.         {
  896.             width = this->GetColWidth(1);
  897.             leftEdge = IntMultiply((short)width, aCol - 1);//!!! cast
  898.             width = IntMultiply((short)width, numOfCols);//!!! cast
  899.         }
  900.         else
  901.         {
  902.             leftEdge = fColWidths->SumValues(1, aCol - 1);
  903.             width = fColWidths->SumValues(aCol, numOfCols);
  904.         }
  905.  
  906.         aRect = VRect(0, leftEdge, fRowHeights->fTotal, leftEdge + width);
  907.     }
  908. }
  909.  
  910. //--------------------------------------------------------------------------------------------------
  911. #pragma segment GVRes
  912.  
  913. pascal void TGridView::AddStrip(RgnHandle thePixels,
  914.                      VHSelect direction,
  915.                      short& startOfStrip,
  916.                      short endOfStrip,
  917.                      Rect& stripRect,
  918.                      short row,
  919.                      short col,
  920.                      VRect& pixels,
  921.                      VRect& prevPixels,
  922.                      Rect& prevstripRect)
  923. {
  924.     Rect qdRect;
  925.  
  926.     if (direction == vSel)
  927.         stripRect = Rect(startOfStrip, col, endOfStrip, col);
  928.     else
  929.         stripRect = Rect(row, startOfStrip, row, endOfStrip);
  930.  
  931. #if qDebugMsg
  932.     if (gIntenseDebugging)
  933.     {
  934.         WrLblRect("Adding cells", stripRect);
  935.         fprintf(stderr, "\n");
  936.     }
  937. #endif
  938.  
  939.     pixels = prevPixels;
  940.  
  941.     if (stripRect.top != prevstripRect.top)
  942.         pixels.top = this->fRowHeights->SumValues(1, stripRect.top - 1);
  943.     if (stripRect.bottom != prevstripRect.bottom)
  944.     {
  945.         if (stripRect.bottom == stripRect.top)
  946.             pixels.bottom = pixels.top + this->fRowHeights->GetValue(stripRect.bottom);
  947.         else
  948.             pixels.bottom = this->fRowHeights->SumValues(1, stripRect.bottom);
  949.     }
  950.     if (stripRect.left != prevstripRect.left)
  951.         pixels.left = this->fColWidths->SumValues(1, stripRect.left - 1);
  952.     if (stripRect.right != prevstripRect.right)
  953.     {
  954.         if (stripRect.right == stripRect.left)
  955.             pixels.right = pixels.left + this->fColWidths->GetValue(stripRect.right);
  956.         else
  957.             pixels.right = this->fColWidths->SumValues(1, stripRect.right);
  958.     }
  959.     
  960.     prevPixels = pixels;
  961.  
  962. #if qDebug
  963.     UseTempRgn("TGridView::AddStrip()");
  964. #endif
  965.     SetEmptyRgn(gTempRgn);
  966.     this->ViewToQDRect(pixels, qdRect);
  967.     RectRgn(gTempRgn, qdRect);
  968.     UnionRgn(gTempRgn, thePixels, thePixels);
  969. #if qDebug
  970.     DoneWithTempRgn();
  971. #endif
  972.  
  973.     prevstripRect = stripRect;
  974.     startOfStrip = 0;
  975. }
  976.  
  977.  
  978. pascal void TGridView::CellsToPixels(RgnHandle theCells,
  979.                                      RgnHandle thePixels)
  980.  
  981. {
  982.     Rect cellBounds;
  983.     VRect visibleVRect;
  984.     Rect visibleCells;
  985.     Rect stripRect;
  986.     GridCell aCell;
  987.     short row,
  988.      col;
  989.     VRect pixels;
  990.     VRect prevPixels;
  991.     Rect prevstripRect;
  992.     VHSelect direction;
  993.     short startOfStrip;
  994.  
  995.     SetEmptyRgn(thePixels);
  996.  
  997.     if (!EmptyRgn(theCells) && this->Focus())
  998.         if ((*theCells)->rgnSize == 10)            // the region is a rectangle 
  999.         {
  1000.             cellBounds = (**theCells).rgnBBox;
  1001.             pixels = VRect(fRowHeights->SumValues(1, cellBounds.top - 1), fColWidths->SumValues(1, cellBounds.left - 1),
  1002.                            fRowHeights->SumValues(1, cellBounds.bottom - 1), fColWidths->SumValues(1, cellBounds.right - 1));
  1003.             this->ViewToQDRect(pixels, (**thePixels).rgnBBox);
  1004.         }
  1005.         else
  1006.         {
  1007.             // Reduce the cells to only those that are visible 
  1008.             this->GetVisibleRect(visibleVRect);
  1009.             // !!!FIX the following 2 lines after MPW C compiler bug is corrected.
  1010.             GridCell temp = this->VPointToLastCell(visibleVRect[topLeft]);
  1011.             visibleCells[topLeft] = temp;
  1012.             // !!!FIX the following 2 lines after MPW C compiler bug is corrected.
  1013.             temp = this->VPointToLastCell(visibleVRect[botRight]);
  1014.             visibleCells[botRight] = temp;
  1015.             SetRectRgn(pVisibleCells, visibleCells.left, visibleCells.top, visibleCells.right + 1, visibleCells.bottom + 1);
  1016.             SectRgn(theCells, pVisibleCells, pVisibleCells);
  1017.             cellBounds = (**pVisibleCells).rgnBBox;
  1018.  
  1019.             prevstripRect = gZeroRect;
  1020.             direction = LongerSide(cellBounds);
  1021.             if (direction == vSel)
  1022.                 for (col = cellBounds.left; col < cellBounds.right; ++col)
  1023.                 {
  1024.                     aCell.h = col;
  1025.                     startOfStrip = 0;
  1026.                     for (row = cellBounds.top; row < cellBounds.bottom; ++row)
  1027.                     {
  1028.                         aCell.v = row;
  1029.                         if (PtInRgn(aCell, pVisibleCells))
  1030.                         {
  1031.                             if (startOfStrip == 0)
  1032.                                 startOfStrip = row;
  1033.                         }
  1034.                         else if (startOfStrip > 0)
  1035.                             this->AddStrip(thePixels, direction, startOfStrip, row - 1, stripRect, row, col, pixels, prevPixels, prevstripRect);
  1036.                     }
  1037.                     if (startOfStrip > 0)
  1038.                         this->AddStrip(thePixels, direction, startOfStrip, cellBounds.bottom - 1, stripRect, row, col, pixels, prevPixels, prevstripRect);
  1039.                 }
  1040.             else
  1041.                 for (row = cellBounds.top; row < cellBounds.bottom; ++row)
  1042.                 {
  1043.                     aCell.v = row;
  1044.                     startOfStrip = 0;
  1045.                     for (col = cellBounds.left; col < cellBounds.right; ++col)
  1046.                     {
  1047.                         aCell.h = col;
  1048.                         if (PtInRgn(aCell, pVisibleCells))
  1049.                         {
  1050.                             if (startOfStrip == 0)
  1051.                                 startOfStrip = col;
  1052.                         }
  1053.                         else if (startOfStrip > 0)
  1054.                             this->AddStrip(thePixels, direction, startOfStrip, col - 1, stripRect, row, col, pixels, prevPixels, prevstripRect);
  1055.                     }
  1056.                     if (startOfStrip > 0)
  1057.                         this->AddStrip(thePixels, direction, startOfStrip, cellBounds.right - 1, stripRect, row, col, pixels, prevPixels, prevstripRect);
  1058.                 }
  1059.         }
  1060. }
  1061.  
  1062. //--------------------------------------------------------------------------------------------------
  1063. #pragma segment GVRes
  1064.  
  1065. pascal void TGridView::DoHighlightSelection(HLState fromHL,
  1066.                                             HLState toHL)// override 
  1067. {
  1068.     if (!EmptyRgn(fHLRegion))
  1069.         this->HighlightCells(fHLRegion, fromHL, toHL);
  1070. }
  1071.  
  1072. //--------------------------------------------------------------------------------------------------
  1073. #pragma segment GVRes
  1074.  
  1075. pascal void TGridView::HighlightCells(RgnHandle theCells,
  1076.                                       HLState fromHL,
  1077.                                       HLState toHL)
  1078. {
  1079.     if (fromHL == hlDim)                        // GridViews don't support dim highlighting 
  1080.         fromHL = hlOff;
  1081.     if (toHL == hlDim)
  1082.         toHL = hlOff;
  1083.  
  1084.     if ((fromHL != toHL) && this->Focus())
  1085.     {
  1086.         this->CellsToPixels(theCells, pPixelsToHighlight);
  1087.  
  1088.         PenNormal();
  1089.         UseSelectionColor();
  1090.         InvertRgn(pPixelsToHighlight);            // highlight the cells 
  1091.     }
  1092. }
  1093.  
  1094. //--------------------------------------------------------------------------------------------------
  1095. #pragma segment GVRes
  1096.  
  1097. pascal void TGridView::DoMouseCommand(VPoint& theMouse,
  1098.                                       TToolboxEvent* event,
  1099.                                       Point)    // override 
  1100. {
  1101.     short aRow;
  1102.     short aCol;
  1103.  
  1104.     if (this->IdentifyPoint(theMouse, aRow, aCol) != badChoice)
  1105.     {
  1106.         TCellSelectCommand * aCellSelectCommand = new TCellSelectCommand;
  1107.         aCellSelectCommand->ICellSelectCommand(this, theMouse, event->fShiftKey, event->fCmdKey);
  1108.         this->PostCommand(aCellSelectCommand);
  1109.     }
  1110. }
  1111.  
  1112. //--------------------------------------------------------------------------------------------------
  1113. #pragma segment GVRes
  1114.  
  1115. pascal void TGridView::Draw(const VRect& area)    // override 
  1116. {
  1117.     VRect aRect;
  1118.     VRect bRect;
  1119.     register short i;
  1120.     GridCell startCell;
  1121.     GridCell stopCell;
  1122.     VRect viewArea;
  1123.     GridCell startCellToDraw;
  1124.     VRect cellsArea;
  1125.     VRect localArea(area);                        // use localArea (because area is const)
  1126.  
  1127.     if ((fNumOfRows > 0) && (fNumOfCols > 0))
  1128.     {
  1129.         // make sure we have something to draw 
  1130.         viewArea = localArea;
  1131.  
  1132.         startCell = this->VPointToLastCell(viewArea[topLeft]);
  1133.         stopCell = this->VPointToLastCell(viewArea[botRight]);
  1134.  
  1135.         this->CellToVRect(startCell, aRect);
  1136.         this->CellToVRect(stopCell, bRect);
  1137.         bRect[topLeft] = aRect[topLeft];
  1138.         localArea = bRect;
  1139.  
  1140.         startCellToDraw = startCell;
  1141.         cellsArea = localArea;
  1142.         if (viewArea.top >= aRect.bottom - (fRowInset / 2))     //((fRowInset) >> 1)
  1143.         {
  1144.             ++startCellToDraw.v;
  1145.             cellsArea.top += aRect.Length(vSel);
  1146.         }
  1147.  
  1148.         this->DrawRangeOfCells(startCellToDraw, stopCell, cellsArea);
  1149.  
  1150.         if (fAdornCols)
  1151.         {
  1152.             short colWidth = 0;
  1153.             aRect = localArea;
  1154.  
  1155.             register Boolean constantWidth = fColWidths->fNoOfChunks == 1;
  1156.             if (constantWidth)                    // only one width 
  1157.                 colWidth = this->GetColWidth(1);
  1158.  
  1159.             for (i = startCell.h; i <= stopCell.h; ++i)
  1160.             {
  1161.                 if (constantWidth)
  1162.                     aRect.right = aRect.left + colWidth;
  1163.                 else
  1164.                     aRect.right = aRect.left + this->GetColWidth(i);
  1165.  
  1166.                 this->AdornCol(i, aRect);
  1167.                 aRect.left = aRect.right;
  1168.             }
  1169.         }
  1170.  
  1171.         if (fAdornRows)
  1172.         {
  1173.             short rowHeight = 0;
  1174.             aRect = localArea;
  1175.  
  1176.             register Boolean constantHeight = fRowHeights->fNoOfChunks == 1;
  1177.             if (constantHeight)                    // only one height 
  1178.                 rowHeight = this->GetRowHeight(1);
  1179.  
  1180.             for (i = startCell.v; i <= stopCell.v; ++i)
  1181.             {
  1182.                 if (constantHeight)
  1183.                     aRect.bottom = aRect.top + rowHeight;
  1184.                 else
  1185.                     aRect.bottom = aRect.top + this->GetRowHeight(i);
  1186.  
  1187.                 this->AdornRow(i, aRect);
  1188.                 aRect.top = aRect.bottom;
  1189.             }
  1190.         }
  1191.     }
  1192.  
  1193.     inherited::Draw(localArea);
  1194. }
  1195.  
  1196. //--------------------------------------------------------------------------------------------------
  1197. #pragma segment GVRes
  1198.  
  1199. pascal void TGridView::DrawRangeOfCells(GridCell startCell,
  1200.                                         GridCell stopCell,
  1201.                                         const VRect& aRect)
  1202. {
  1203.     VCoordinate colWidth;
  1204.     VCoordinate rowHeight;
  1205.     short i,
  1206.      j;
  1207.     GridCell aCell;
  1208.     VCoordinate left;
  1209.     VRect localVRect;                            //!!! added because argument is const
  1210.  
  1211.     localVRect = aRect;                            //!!! added because argument is const
  1212.     localVRect.left += fColInset / 2;
  1213.     localVRect.top += fRowInset / 2;
  1214.     left = localVRect.left;
  1215.  
  1216.     if (fColWidths->fNoOfChunks == 1)            // only one width 
  1217.         colWidth = this->GetColWidth(1);
  1218.     if (fRowHeights->fNoOfChunks == 1)            // only one height 
  1219.         rowHeight = this->GetRowHeight(1);
  1220.  
  1221.     for (j = startCell.v; j <= stopCell.v; ++j)
  1222.     {
  1223.         if (fRowHeights->fNoOfChunks == 1)        // only one height 
  1224.             localVRect.bottom = localVRect.top + rowHeight - fRowInset;
  1225.         else
  1226.             localVRect.bottom = localVRect.top + this->GetRowHeight(j) - fRowInset;
  1227.  
  1228.         localVRect.left = left;                    // start back at the left for the next row 
  1229.  
  1230.         for (i = startCell.h; i <= stopCell.h; ++i)
  1231.         {
  1232.             if (fColWidths->fNoOfChunks == 1)    // only one height 
  1233.                 localVRect.right = localVRect.left + colWidth - fColInset;
  1234.             else
  1235.                 localVRect.right = localVRect.left + this->GetColWidth(i) - fColInset;
  1236.  
  1237.             aCell.h = i;
  1238.             aCell.v = j;
  1239.             this->DrawCell(aCell, localVRect);
  1240.  
  1241.             localVRect.left = localVRect.right + fColInset;
  1242.         }
  1243.         localVRect.top = localVRect.bottom + fRowInset;
  1244.     }
  1245. }
  1246.  
  1247. //--------------------------------------------------------------------------------------------------
  1248. #pragma segment GVRes
  1249.  
  1250. pascal void TGridView::DrawCell(GridCell        /* aCell */,
  1251.                                 const VRect&    /* aRect */)
  1252. {
  1253.     this->SubClassResponsibility();
  1254. }
  1255.  
  1256. //--------------------------------------------------------------------------------------------------
  1257. #pragma segment GVNonRes
  1258.  
  1259. pascal void TGridView::DelColAt(short aCol,
  1260.                                 short numOfCols)
  1261. {
  1262.     VRect aRect;
  1263.  
  1264.     if ((aCol < 1) || (numOfCols < 1) || (aCol + numOfCols - 1 > fNumOfCols))
  1265.     {
  1266.         if (numOfCols != 0)
  1267.         {
  1268. #if qDebugMsg
  1269.             fprintf(stderr, "fNumOfCols == %1d   aCol == %1d\n", fNumOfCols, aCol);
  1270.             ProgramBreak("Range Check in DelColAt");
  1271.             return;
  1272. #endif
  1273.  
  1274.         }
  1275.     }
  1276.     else
  1277.     {
  1278.         this->ColToVRect((short)Max(1, aCol), (short)Max(1, fNumOfCols - aCol + 1), aRect);//!!! cast
  1279.         fColWidths->DeleteItems(aCol, numOfCols);
  1280.         fNumOfCols = fNumOfCols - numOfCols;
  1281.         this->AdjustSize();
  1282.         this->InvalidateVRect(aRect);
  1283.     }
  1284. }
  1285.  
  1286. //--------------------------------------------------------------------------------------------------
  1287. #pragma segment GVNonRes
  1288.  
  1289. pascal void TGridView::DelRowAt(short aRow,
  1290.                                 short numOfRows)
  1291. {
  1292.     VRect aRect;
  1293.  
  1294.     if ((aRow < 1) || (numOfRows < 1) || (aRow + numOfRows - 1 > fNumOfRows))
  1295.     {
  1296.         if (numOfRows != 0)
  1297.         {
  1298. #if qDebugMsg
  1299.             fprintf(stderr, "fNumOfRows == %1d  aRow == %1d\n", fNumOfRows, aRow);
  1300.             ProgramBreak("Range Check in DelRowAt");
  1301.             return;
  1302. #endif
  1303.  
  1304.         }
  1305.     }
  1306.     else
  1307.     {
  1308.         this->RowToVRect((short)Max(1, aRow), (short)Max(1, fNumOfRows - aRow + 1), aRect);//!!! cast
  1309.         fRowHeights->DeleteItems(aRow, numOfRows);
  1310.         fNumOfRows = fNumOfRows - numOfRows;
  1311.         this->AdjustSize();
  1312.         this->InvalidateVRect(aRect);
  1313.     }
  1314. }
  1315.  
  1316. //--------------------------------------------------------------------------------------------------
  1317. #pragma segment GVNonRes
  1318.  
  1319. pascal void TGridView::DelColFirst(short numOfCols)
  1320. {
  1321.     this->DelColAt(1, numOfCols);
  1322. }
  1323.  
  1324. //--------------------------------------------------------------------------------------------------
  1325. #pragma segment GVNonRes
  1326.  
  1327. pascal void TGridView::DelRowFirst(short numOfRows)
  1328. {
  1329.     this->DelRowAt(1, numOfRows);
  1330. }
  1331.  
  1332. //--------------------------------------------------------------------------------------------------
  1333. #pragma segment GVNonRes
  1334.  
  1335. pascal void TGridView::DelColLast(short numOfCols)
  1336. {
  1337.     this->DelColAt(fNumOfCols - numOfCols + 1, numOfCols);
  1338. }
  1339.  
  1340. //--------------------------------------------------------------------------------------------------
  1341. #pragma segment GVNonRes
  1342.  
  1343. pascal void TGridView::DelRowLast(short numOfRows)
  1344. {
  1345.     this->DelRowAt(fNumOfRows - numOfRows + 1, numOfRows);
  1346. }
  1347.  
  1348. //--------------------------------------------------------------------------------------------------
  1349. #pragma segment GVRes
  1350.  
  1351. pascal void TGridView::EachCellDo(GridCell startCell,
  1352.                                   GridCell stopCell,
  1353.                                   pascal void(* DoToCell)(GridCell aCell,
  1354.                                                           void* staticLink),
  1355.                                   void* staticLink)
  1356. {
  1357.     short i,
  1358.      j;
  1359.     short firstRow;
  1360.     short lastRow;
  1361.     short firstCol;
  1362.     short lastCol;
  1363.     GridCell aCell;
  1364.  
  1365.     firstRow = (short)Max(1, startCell.v);        //!!! Cast
  1366.     firstCol = (short)Max(1, startCell.h);        //!!! Cast
  1367.     lastRow = (short)Min(fNumOfRows, stopCell.v);//!!! Cast
  1368.     lastCol = (short)Min(fNumOfCols, stopCell.h);//!!! Cast
  1369.  
  1370.     for (j = firstRow; j <= lastRow; ++j)
  1371.     {
  1372.         aCell.v = j;
  1373.         for (i = firstCol; i <= lastCol; ++i)
  1374.         {
  1375.             aCell.h = i;
  1376.             DoToCell(aCell, staticLink);
  1377.         }
  1378.     }
  1379. }
  1380.  
  1381. //--------------------------------------------------------------------------------------------------
  1382. #pragma segment GVRes
  1383.  
  1384. pascal void TGridView::EachColDo(short startCol,
  1385.                                  short stopCol,
  1386.                                  pascal void(* DoToCol)(short aCol,
  1387.                                                         void* staticLink),
  1388.                                  void* staticLink)
  1389. {
  1390.     short firstCol;
  1391.     short lastCol;
  1392.  
  1393.     firstCol = (short)Max(1, startCol);            //!!! Cast
  1394.     lastCol = (short)Min(fNumOfCols, stopCol);    //!!! Cast
  1395.  
  1396.     for (short i = firstCol; i <= lastCol; ++i)
  1397.         DoToCol(i, staticLink);
  1398. }
  1399.  
  1400. //--------------------------------------------------------------------------------------------------
  1401. #pragma segment GVRes
  1402.  
  1403. pascal void TGridView::EachRowDo(short startRow,
  1404.                                  short stopRow,
  1405.                                  pascal void(* DoToRow)(short aRow,
  1406.                                                         void* staticLink),
  1407.                                  void* staticLink)
  1408. {
  1409.     short firstRow;
  1410.     short lastRow;
  1411.  
  1412.     firstRow = (short)Max(1, startRow);            //!!! Cast
  1413.     lastRow = (short)Min(fNumOfRows, stopRow);    //!!! Cast
  1414.  
  1415.     for (short i = firstRow; i <= lastRow; ++i)
  1416.         DoToRow(i, staticLink);
  1417. }
  1418.  
  1419. //--------------------------------------------------------------------------------------------------
  1420. #pragma segment GVRes
  1421.  
  1422. pascal void TGridView::EachSelectedCellDo(pascal void(* DoToCell)(GridCell aCell,
  1423.                                                                   void* staticLink),
  1424.                                           void* staticLink)
  1425. {
  1426.     this->EachInRgn(fSelections, DoToCell, staticLink);
  1427. }
  1428.  
  1429. //--------------------------------------------------------------------------------------------------
  1430. #pragma segment GVRes
  1431.  
  1432. pascal void TGridView::EachInRgn(RgnHandle aRgn,
  1433.                                  pascal void(* DoToCell)(GridCell aCell,
  1434.                                                          void* staticLink),
  1435.                                  void* staticLink)
  1436. {
  1437.     GridCell aCell;
  1438.     Rect boundsRect;
  1439.  
  1440.     boundsRect = (*aRgn)->rgnBBox;
  1441.     --boundsRect.right;
  1442.     --boundsRect.bottom;
  1443.     if ((**aRgn).rgnSize == 10)                    // its a rectangle
  1444.         this->EachCellDo(boundsRect[topLeft], boundsRect[botRight], DoToCell, staticLink);
  1445.     else
  1446.         for (short row = boundsRect.top; row <= boundsRect.bottom; ++row)
  1447.         {
  1448.             aCell.v = row;
  1449.             for (short col = boundsRect.left; col <= boundsRect.right; ++col)
  1450.             {
  1451.                 aCell.h = col;
  1452.                 if (PtInRgn(aCell, aRgn))
  1453.                     DoToCell(aCell, staticLink);
  1454.             }
  1455.         }
  1456. }
  1457.  
  1458. //--------------------------------------------------------------------------------------------------
  1459. #pragma segment GVRes
  1460.  
  1461. pascal GridCell TGridView::FirstSelectedCell(void)
  1462. {
  1463.     Rect bounds;
  1464.     GridCell aCell;
  1465.     GridCell result;
  1466.  
  1467.     result = gZeroPt;
  1468.     if (this->IsAnyCellSelected())
  1469.     {
  1470.         bounds = (*fSelections)->rgnBBox;
  1471.         if ((**fSelections).rgnSize == 10)        // whole rectangle 
  1472.             result = bounds[topLeft];
  1473.         else
  1474.             for (short i = bounds.top; i <= bounds.bottom - 1; ++i)
  1475.         {
  1476.             aCell.v = i;
  1477.             for (short j = bounds.left; j <= bounds.right - 1; ++j)
  1478.             {
  1479.                 aCell.h = j;
  1480.                 if (PtInRgn(aCell, fSelections))
  1481.                 {
  1482.                     result = aCell;
  1483.                     return result;
  1484.                 }
  1485.             }
  1486.         }
  1487.     }
  1488.     return result;
  1489. }
  1490.  
  1491. //--------------------------------------------------------------------------------------------------
  1492. #pragma segment GVRes
  1493.  
  1494. pascal short TGridView::GetColWidth(short aCol)
  1495. {
  1496.     if ((aCol < 1) || (aCol > fNumOfCols))
  1497.     {
  1498. #if qRangeCheck && qDebugMsg
  1499.         fprintf(stderr, "fNumOfCols == &1d  aCol == %1d\n", fNumOfCols, aCol);
  1500.         ProgramBreak("Range Check in GetColWidth");
  1501. #endif
  1502.  
  1503.         return 0;
  1504.     }
  1505.     else
  1506.         return fColWidths->GetValue(aCol);
  1507. }
  1508.  
  1509. //--------------------------------------------------------------------------------------------------
  1510. #pragma segment GVRes
  1511.  
  1512. pascal short TGridView::GetRowHeight(short aRow)
  1513. {
  1514.     if ((aRow < 1) || (aRow > fNumOfRows))
  1515.     {
  1516. #if qRangeCheck && qDebugMsg
  1517.         fprintf(stderr, "fNumOfRows == &1d  aRow == %1d\n", fNumOfRows, aRow);
  1518.         ProgramBreak("Range Check in GetRowHeight");
  1519. #endif
  1520.  
  1521.         return 0;
  1522.     }
  1523.     else
  1524.         return fRowHeights->GetValue(aRow);
  1525. }
  1526.  
  1527. //--------------------------------------------------------------------------------------------------
  1528. #pragma segment GVRes
  1529.  
  1530. pascal void TGridView::InvalidateCell(GridCell aCell)
  1531. {
  1532.     VRect aRect;
  1533.  
  1534.     this->CellToVRect(aCell, aRect);
  1535.     this->InvalidateVRect(aRect);
  1536. }
  1537.  
  1538. //--------------------------------------------------------------------------------------------------
  1539. #pragma segment GVRes
  1540.  
  1541. pascal void TGridView::InvalidateSelection(void)
  1542. {
  1543.     if (this->Focus())
  1544.     {
  1545.         this->CellsToPixels(fSelections, pInvalidateRgn);
  1546.         this->InvalidateRgn(pInvalidateRgn);
  1547.     }
  1548. }
  1549.  
  1550. //--------------------------------------------------------------------------------------------------
  1551. #pragma segment GVRes
  1552.  
  1553. pascal GridViewPart TGridView::IdentifyPoint(const VPoint& thePoint,
  1554.                                              short& aRow,
  1555.                                              short& aCol)
  1556. {
  1557.     VRect aRect;
  1558.     GridCell aCell;
  1559.     GridViewPart aGridViewPart;
  1560.  
  1561.     aCell = this->VPointToCell(thePoint);
  1562.     aRow = aCell.v;
  1563.     aCol = aCell.h;
  1564.  
  1565.     if (aCell == gZeroPt)
  1566.         aGridViewPart = badChoice;
  1567.     else
  1568.     {
  1569.         this->CellToVRect(aCell, aRect);
  1570.         aRect.Inset(VPoint(fRowInset / 2, fColInset / 2));
  1571.         aGridViewPart = inCell;
  1572.  
  1573.         if (fColInset > 0)
  1574.         {
  1575.             if (thePoint.h < aRect.left)
  1576.             {
  1577.                 aGridViewPart = inColumn;        // To the left of the cell 
  1578.             }
  1579.             else if (thePoint.h >= aRect.right)    /* Remember PtInRgn will report a point as in
  1580.                                                   a region only if the pixel to the right
  1581.                                                   and below the point is contained in the
  1582.                                                   region. */
  1583.             {
  1584.                 aGridViewPart = inColumn;        // To the right of the cell 
  1585.                 ++aCol;
  1586.             }
  1587.         }
  1588.  
  1589.         if (fRowInset > 0)
  1590.         {
  1591.             if (thePoint.v < aRect.top)
  1592.             {
  1593.                 if (aGridViewPart == inColumn)
  1594.                     aGridViewPart = inVertex;    // Click on both 
  1595.                 else
  1596.                     aGridViewPart = inRow;        // Above the cell 
  1597.             }
  1598.             else if (thePoint.v >= aRect.bottom)/* Remember PtInRgn will report a point as in
  1599.                                                   a region only if the pixel to the right
  1600.                                                   and below the point is contained in the
  1601.                                                   region. */
  1602.             {
  1603.                 if (aGridViewPart == inColumn)
  1604.                     aGridViewPart = inVertex;    // Click on both 
  1605.                 else
  1606.                     aGridViewPart = inRow;        // Above the cell 
  1607.                 ++aRow;
  1608.             }
  1609.         }
  1610.     }
  1611.     return aGridViewPart;
  1612. }
  1613.  
  1614. //--------------------------------------------------------------------------------------------------
  1615. #pragma segment GVRes
  1616.  
  1617. pascal void TGridView::InsColBefore(short aCol,
  1618.                                     short numOfCols,
  1619.                                     short aWidth)
  1620. {
  1621.     VRect aRect;
  1622.  
  1623.     if ((aCol < 1) || (numOfCols < 1))
  1624.     {
  1625.         if (numOfCols != 0)
  1626.         {
  1627. #if qDebugMsg && qRangeCheck
  1628.             fprintf(stderr, "fNumOfCols == %1d aCol == %1d", fNumOfCols, aCol);
  1629.             ProgramBreak("Range Check in InsColBefore");
  1630. #endif
  1631.  
  1632.         }
  1633.     }
  1634.     else
  1635.     {
  1636.         fColWidths->InsertItems(aCol, numOfCols, aWidth);
  1637.         fNumOfCols += numOfCols;
  1638.         this->AdjustSize();
  1639.         this->ColToVRect((short)Max(1, aCol), (short)Max(1, fNumOfCols - aCol + 1), aRect);//!!! Cast
  1640.         this->InvalidateVRect(aRect);
  1641.     }
  1642. }
  1643.  
  1644. //--------------------------------------------------------------------------------------------------
  1645. #pragma segment GVRes
  1646.  
  1647. pascal void TGridView::InsRowBefore(short aRow,
  1648.                                     short numOfRows,
  1649.                                     short aHeight)
  1650. {
  1651.     VRect aRect;
  1652.  
  1653.     if ((aRow < 1) || (numOfRows < 1))
  1654.     {
  1655.         if (numOfRows != 0)
  1656.         {
  1657. #if qDebugMsg && qRangeCheck
  1658.             fprintf(stderr, "fNumOfRows == %1d aRow == %1d", fNumOfRows, aRow);
  1659.             ProgramBreak("Range Check in InsRowBefore");
  1660. #endif
  1661.  
  1662.         }
  1663.     }
  1664.     else
  1665.     {
  1666.         fRowHeights->InsertItems(aRow, numOfRows, aHeight);
  1667.         fNumOfRows = fNumOfRows + numOfRows;
  1668.         this->AdjustSize();
  1669.         this->RowToVRect((short)Max(1, aRow), (short)Max(1, fNumOfRows - aRow + 1), aRect);//!!! Cast
  1670.         this->InvalidateVRect(aRect);
  1671.     }
  1672. }
  1673.  
  1674. //--------------------------------------------------------------------------------------------------
  1675. #pragma segment GVRes
  1676.  
  1677. pascal void TGridView::InsColLast(short numOfCols,
  1678.                                   short aWidth)
  1679. {
  1680.     this->InsColBefore(fNumOfCols + 1, numOfCols, aWidth);
  1681. }
  1682.  
  1683. //--------------------------------------------------------------------------------------------------
  1684. #pragma segment GVRes
  1685.  
  1686. pascal void TGridView::InsRowLast(short numOfRows,
  1687.                                   short aHeight)
  1688. {
  1689.     this->InsRowBefore(fNumOfRows + 1, numOfRows, aHeight);
  1690. }
  1691.  
  1692. //--------------------------------------------------------------------------------------------------
  1693. #pragma segment GVRes
  1694.  
  1695. pascal void TGridView::InsColFirst(short numOfCols,
  1696.                                    short aWidth)
  1697. {
  1698.     this->InsColBefore(1, numOfCols, aWidth);
  1699. }
  1700.  
  1701. //--------------------------------------------------------------------------------------------------
  1702. #pragma segment GVRes
  1703.  
  1704. pascal void TGridView::InsRowFirst(short numOfRows,
  1705.                                    short aHeight)
  1706. {
  1707.     this->InsRowBefore(1, numOfRows, aHeight);
  1708. }
  1709.  
  1710. //--------------------------------------------------------------------------------------------------
  1711. #pragma segment GVRes
  1712.  
  1713. pascal Boolean TGridView::IsCellSelected(GridCell aCell)
  1714. {
  1715.     return PtInRgn(aCell, fSelections);
  1716. }
  1717.  
  1718. //--------------------------------------------------------------------------------------------------
  1719. #pragma segment GVRes
  1720.  
  1721. pascal Boolean TGridView::IsAnyCellSelected(void)
  1722. {
  1723.     return !EmptyRgn(fSelections);
  1724. }
  1725.  
  1726. //--------------------------------------------------------------------------------------------------
  1727. #pragma segment GVRes
  1728.  
  1729. pascal GridCell TGridView::LastSelectedCell(void)
  1730. {
  1731.     Rect bounds;
  1732.     GridCell aCell;
  1733.     GridCell result;
  1734.  
  1735.     result = gZeroPt;
  1736.     if (this->IsAnyCellSelected())
  1737.     {
  1738.         bounds = (**fSelections).rgnBBox;
  1739.         if ((**fSelections).rgnSize == 10)        // whole rectangle 
  1740.         {
  1741.             aCell.h = bounds.right - 1;
  1742.             aCell.v = bounds.bottom - 1;
  1743.             result = aCell;
  1744.         }
  1745.         else
  1746.             for (short i = bounds.bottom - 1; i >= bounds.top; i--)
  1747.             {
  1748.                 aCell.v = i;
  1749.                 for (short j = bounds.right - 1; j >= bounds.left; j--)
  1750.                 {
  1751.                     aCell.h = j;
  1752.                     if (PtInRgn(aCell, fSelections))
  1753.                     {
  1754.                         result = aCell;
  1755.                         return result;
  1756.                     }
  1757.                 }
  1758.             }
  1759.     }
  1760.     return result;
  1761. }
  1762.  
  1763. //--------------------------------------------------------------------------------------------------
  1764. #pragma segment GVRes
  1765.  
  1766. pascal void TGridView::RowToVRect(short aRow,
  1767.                                   short numOfRows,
  1768.                                   VRect& aRect)
  1769. {
  1770.     long height;
  1771.     long topEdge;
  1772.  
  1773.     if ((aRow < 1) || (numOfRows < 1) || (aRow + numOfRows - 1 > fNumOfRows))
  1774.     {
  1775. #if qDebugMsg && qRangeCheck
  1776.         fprintf(stderr, "fNumOfRows == %1d aRow == %1d", fNumOfRows, aRow);
  1777.         ProgramBreak("Range Check in RowToVRect");
  1778. #endif
  1779.  
  1780.         aRect = gZeroVRect;
  1781.     }
  1782.     else                                        // all the params look OK 
  1783.     {
  1784.         if (fRowHeights->fNoOfChunks == 1)        // only one row height 
  1785.         {
  1786.             height = fRowHeights->GetValue(1);
  1787.             topEdge = IntMultiply((short)height, aRow - 1);//!!! Cast
  1788.             height = IntMultiply((short)height, numOfRows);//!!! Cast
  1789.         }
  1790.         else
  1791.         {
  1792.             topEdge = fRowHeights->SumValues(1, aRow - 1);
  1793.             height = fRowHeights->SumValues(aRow, numOfRows);
  1794.         }
  1795.  
  1796.         aRect = VRect(topEdge, 0, topEdge + height, fColWidths->fTotal);
  1797.     }
  1798. }
  1799.  
  1800. //--------------------------------------------------------------------------------------------------
  1801. #pragma segment GVRes
  1802.  
  1803. pascal void TGridView::ScrollSelectionIntoView(Boolean redraw)
  1804. {
  1805.     VRect topLeftRect;
  1806.     VRect botRightRect;
  1807.     VRect selectionRect;
  1808.  
  1809.     if (this->IsAnyCellSelected())
  1810.     {
  1811.         this->CellToVRect((**fSelections).rgnBBox[topLeft], topLeftRect);
  1812.         GridCell botRightCell((**fSelections).rgnBBox.bottom - 1, (**fSelections).rgnBBox.right - 1);
  1813.         this->CellToVRect(botRightCell, botRightRect);
  1814.         selectionRect = topLeftRect | botRightRect;
  1815.         VPoint minToSee(Max(topLeftRect.Length(vSel), botRightRect.Length(vSel)),
  1816.                     Max(topLeftRect.Length(hSel), botRightRect.Length(hSel)));
  1817.         this->RevealRect(selectionRect, minToSee, redraw);
  1818.     }
  1819. }
  1820.  
  1821. //--------------------------------------------------------------------------------------------------
  1822. #pragma segment GVNonRes
  1823.  
  1824. pascal void TGridView::SetColWidth(short aCol,
  1825.                                    short numOfCols,
  1826.                                    short aWidth)
  1827. {
  1828.     VRect aRect;
  1829.  
  1830. #if qDebugMsg
  1831.     if ((aCol < 1) || (numOfCols < 1) || (aCol + numOfCols - 1 > fNumOfCols))
  1832.     {
  1833.         fprintf(stderr, "fNumOfCols == %1d aCol == %1d", fNumOfCols, aCol);
  1834.         ProgramBreak("Range Check in SetColWidth");
  1835.         return;
  1836.     }
  1837. #endif
  1838.  
  1839.     if ((fColWidths->fNoOfChunks > 1) || (this->GetColWidth(1) != aWidth))
  1840.     {
  1841.         fColWidths->DeleteItems(aCol, numOfCols);
  1842.         fColWidths->InsertItems(aCol, numOfCols, aWidth);
  1843.         this->AdjustSize();
  1844.         this->ColToVRect((short)Max(1, aCol), (short)Max(1, fNumOfCols - aCol + 1), aRect);//!!! Cast
  1845.         this->InvalidateVRect(aRect);
  1846.     }
  1847. }
  1848.  
  1849. //--------------------------------------------------------------------------------------------------
  1850. #pragma segment GVNonRes
  1851.  
  1852. pascal void TGridView::SetRowHeight(short aRow,
  1853.                                     short numOfRows,
  1854.                                     short aHeight)
  1855. {
  1856.     VRect aRect;
  1857.  
  1858. #if qDebugMsg
  1859.     if ((aRow < 1) || (numOfRows < 1) || (aRow + numOfRows - 1 > fNumOfRows))
  1860.     {
  1861.         fprintf(stderr, "fNumOfRows == %1d aRow == %1d", fNumOfRows, aRow);
  1862.         ProgramBreak("Range Check in SetRowHeight.");
  1863.         return;
  1864.     }
  1865. #endif
  1866.  
  1867.     if (!((fRowHeights->fNoOfChunks == 1) && (this->GetRowHeight(1) == aHeight)))
  1868.     {
  1869.         fRowHeights->DeleteItems(aRow, numOfRows);
  1870.         fRowHeights->InsertItems(aRow, numOfRows, aHeight);
  1871.         this->AdjustSize();
  1872.         this->RowToVRect((short)Max(1, aRow), (short)Max(1, fNumOfRows - aRow + 1), aRect);//!!! Cast
  1873.         this->InvalidateVRect(aRect);
  1874.     }
  1875. }
  1876.  
  1877. //--------------------------------------------------------------------------------------------------
  1878. #pragma segment GVRes
  1879.  
  1880. pascal void TGridView::SelectCell(GridCell theCell,
  1881.                                   Boolean extendSelection,
  1882.                                   Boolean highlight,
  1883.                                   Boolean select)
  1884. {
  1885.     this->SetSelectionRect(theCell.h, theCell.v, theCell.h, theCell.v, extendSelection, highlight, select);
  1886. }
  1887.  
  1888. //--------------------------------------------------------------------------------------------------
  1889. #pragma segment GVRes
  1890.  
  1891. pascal void TGridView::SetEmptySelection(Boolean highlight)
  1892. {
  1893.     SetEmptyRgn(fTempSelections);
  1894.     this->SetSelection(fTempSelections, kDontExtend, highlight, kSelect);
  1895. }
  1896.  
  1897. //--------------------------------------------------------------------------------------------------
  1898. #pragma segment GVRes
  1899.  
  1900. pascal void TGridView::SetSelection(RgnHandle cellsToSelect,
  1901.                                     Boolean extendSelection,
  1902.                                     Boolean highlight,
  1903.                                     Boolean select)
  1904. {
  1905. #if qDebug
  1906.     Rect & bounds = (**cellsToSelect).rgnBBox;
  1907.  
  1908.     if (fSingleSelection && ((bounds.Length(hSel) > 1) || (bounds.Length(vSel) > 1)))
  1909.         ProgramBreak("Attempt to select multiple cells when fSingleSelection is true");
  1910.     if (!EmptyRgn(cellsToSelect))
  1911.         if ((bounds.left < 1) || (bounds.top < 1) || (bounds.right > fNumOfCols + 1) || (bounds.bottom > fNumOfRows + 1))
  1912.             ProgramBreak("Attempted selection is outside the range of cells");
  1913. #endif
  1914.  
  1915.     if (highlight)
  1916.         CopyRgn(fSelections, pPreviousSelection);// save the old selection 
  1917.  
  1918. #if qDebug
  1919.     UseTempRgn("TGridView.SetSelection");
  1920. #endif
  1921.  
  1922.     SetRectRgn(gTempRgn, 1, 1, fNumOfCols + 1, fNumOfRows + 1);
  1923.     SectRgn(cellsToSelect, gTempRgn, gTempRgn);
  1924.  
  1925.     if (extendSelection && select)                // extend the selection region 
  1926.         UnionRgn(gTempRgn, fSelections, fSelections);
  1927.     else if (select)                            // reset the selection region 
  1928.         CopyRgn(gTempRgn, fSelections);
  1929.     else                                        // need to de-select the new region 
  1930.         DiffRgn(fSelections, gTempRgn, fSelections);
  1931. #if qDebug
  1932.     DoneWithTempRgn();
  1933. #endif
  1934.  
  1935.     this->UserSelectionChanged();                        // so doc updates its designator 
  1936.  
  1937.     CopyRgn(fSelections, fHLRegion);
  1938.  
  1939.     if (highlight)
  1940.     {
  1941.         // Turn the deselected cells off 
  1942.         DiffRgn(pPreviousSelection, fSelections, pDifference);
  1943.         this->HighlightCells(pDifference, fHLDesired, hlOff);
  1944.  
  1945.         // Turn the newly selected cells on 
  1946.         DiffRgn(fSelections, pPreviousSelection, pDifference);
  1947.         this->HighlightCells(pDifference, hlOff, fHLDesired);
  1948.     }
  1949. }
  1950.  
  1951. //--------------------------------------------------------------------------------------------------
  1952. #pragma segment GVRes
  1953.  
  1954. pascal void TGridView::SetSelectionRect(short left,
  1955.                                         short top,
  1956.                                         short right,
  1957.                                         short bottom,
  1958.                                         Boolean extendSelection,
  1959.                                         Boolean highlight,
  1960.                                         Boolean select)
  1961.  
  1962. {
  1963.     if ((left == 0) && (top == 0) && (right == 0) && (bottom == 0))
  1964.         SetEmptyRgn(fTempSelections);
  1965.     else
  1966.         SetRectRgn(fTempSelections, left, top, right + 1, bottom + 1);
  1967.     this->SetSelection(fTempSelections, extendSelection, highlight, select);
  1968. }
  1969.  
  1970. //--------------------------------------------------------------------------------------------------
  1971. #pragma segment GVNonRes
  1972.  
  1973. pascal void TGridView::SetSingleSelection(Boolean theSetting)
  1974. {
  1975.     fSingleSelection = theSetting;
  1976. }
  1977.  
  1978. //--------------------------------------------------------------------------------------------------
  1979. #pragma segment GVRes
  1980.  
  1981. pascal GridCell TGridView::VPointToCell(const VPoint& aPoint)
  1982. {
  1983.     GridCell aCell(fRowHeights->FindItem(aPoint.v), fColWidths->FindItem(aPoint.h));
  1984.  
  1985.     if ((aCell.h == 0) || (aCell.v == 0))
  1986.         return gZeroPt;
  1987.     else
  1988.         return aCell;
  1989. }
  1990.  
  1991. //--------------------------------------------------------------------------------------------------
  1992. #pragma segment GVRes
  1993.  
  1994. pascal GridCell TGridView::VPointToLastCell(const VPoint& aPoint)
  1995. {
  1996.     GridCell aCell;
  1997.  
  1998.     aCell.h = fColWidths->FindItem(aPoint.h);
  1999.     if (aCell.h == 0)                            // If its invalid, return the last column 
  2000.         aCell.h = fNumOfCols;
  2001.  
  2002.     aCell.v = fRowHeights->FindItem(aPoint.v);
  2003.     if (aCell.v == 0)                            // If its invalid, return the last row 
  2004.         aCell.v = fNumOfRows;
  2005.  
  2006.     return aCell;
  2007. }
  2008.  
  2009. //--------------------------------------------------------------------------------------------------
  2010. #pragma segment GVFields
  2011.  
  2012. pascal void TGridView::Fields(TObject* obj)        // override 
  2013. {
  2014.     obj->DoToField("TGridView", NULL, bClass);
  2015.     obj->DoToField("fSelections", &fSelections, bRgnHandle);
  2016.     obj->DoToField("fHLRegion", &fHLRegion, bRgnHandle);
  2017.     obj->DoToField("fTempSelections", &fTempSelections, bRgnHandle);
  2018.     obj->DoToField("fNumOfRows", &fNumOfRows, bInteger);
  2019.     obj->DoToField("fRowHeights", &fRowHeights, bObject);
  2020.     obj->DoToField("fNumOfCols", &fNumOfCols, bInteger);
  2021.     obj->DoToField("fColWidths", &fColWidths, bObject);
  2022.     obj->DoToField("fRowInset", &fRowInset, bInteger);
  2023.     obj->DoToField("fColInset", &fColInset, bInteger);
  2024.     obj->DoToField("fAdornRows", &fAdornRows, bBoolean);
  2025.     obj->DoToField("fAdornCols", &fAdornCols, bBoolean);
  2026.     obj->DoToField("fSingleSelection", &fSingleSelection, bBoolean);
  2027.  
  2028.     inherited::Fields(obj);
  2029. }
  2030.  
  2031. //--------------------------------------------------------------------------------------------------
  2032. #pragma segment GVOpen
  2033.  
  2034. pascal void TTextGridView::Initialize(void)        // override 
  2035. {
  2036.     inherited::Initialize();
  2037.  
  2038.     fTextStyle = gSystemStyle;
  2039.     fLineHeight = 0;                            // ??? WHat should we do here? 
  2040.     fLineAscent = 0;
  2041. }
  2042.  
  2043. //--------------------------------------------------------------------------------------------------
  2044. #pragma segment GVOpen
  2045.  
  2046. pascal void TTextGridView::ITextGridView(TDocument* itsDocument,
  2047.                                          // Its document 
  2048.                                          TView* itsSuperView,
  2049.                                          // Its parent view 
  2050.                                          const VPoint& itsLocation,
  2051.                                          // Top, Left in parent's coords 
  2052.                                          const VPoint& itsSize,
  2053.                                          SizeDeterminer itsHSizeDet,
  2054.                                          SizeDeterminer itsVSizeDet,
  2055.                                          // Size determiners 
  2056.                                          short numOfRows,
  2057.                                          // Number of rows initially 
  2058.                                          short numOfCols,
  2059.                                          // Number of columns initially 
  2060.                                          short rowHeight,
  2061.                                          // Row height, or zero for font height 
  2062.                                          short colWidth,
  2063.                                          // Width of items in the columns 
  2064.                                          Boolean adornRows,
  2065.                                          // Adornment for Rows? 
  2066.                                          Boolean adornCols,
  2067.                                          // Adornment for Columns? 
  2068.                                          short rowInset,
  2069.                                          // horizontal space between cells 
  2070.                                          short colInset,
  2071.                                          // vertical space between cells 
  2072.                                          Boolean singleSelection,
  2073.                                          // single cell selection? 
  2074.                                          const TextStyle& itsTextStyle)// size, color, etc. font info 
  2075.  
  2076. {
  2077.  
  2078.     fTextStyle = itsTextStyle;
  2079.  
  2080.     this->SetUpFont();
  2081.     if (rowHeight == 0)
  2082.         rowHeight = fLineHeight + rowInset;
  2083.  
  2084.     this->IGridView(itsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet, numOfRows, numOfCols, rowHeight, colWidth, adornRows, adornCols, rowInset, colInset, singleSelection);
  2085.  
  2086.     if ((fNumOfCols == 1) && (fSizeDeterminer[hSel] != sizeFixed) && (this->GetColWidth(1) == 0) && (fSuperView != NULL))
  2087.         this->SetColWidth(1, fNumOfCols, (short)fSuperView->fSize.h);//!!! Note cast
  2088. }
  2089.  
  2090. //--------------------------------------------------------------------------------------------------
  2091. #pragma segment GVOpen
  2092.  
  2093. pascal void TTextGridView::IRes(TDocument* itsDocument,
  2094.                                 TView* itsSuperView,
  2095.                                 Ptr& itsParams)    // override 
  2096. {
  2097.     TextStyle itsTextStyle;
  2098.  
  2099.     // The ancestor will need to focus when adding rows or columns.
  2100.     //  Get the information necessary to focus since this class sets textStyle when focusing
  2101.     fTextStyle = gSystemStyle;                    // Put in safe state 
  2102.  
  2103.     inherited::IRes(itsDocument, itsSuperView, itsParams);
  2104.  
  2105.     {
  2106.         TextGridViewTemplate& templateData = *((TextGridViewTemplate *) itsParams);
  2107.  
  2108.         SetTextStyle(itsTextStyle, GetFontNum(templateData.itsFontName), templateData.itsFontFace, templateData.itsFontSize, templateData.itsFontColor);
  2109.     }
  2110.     fTextStyle = itsTextStyle;
  2111.  
  2112.     this->SetUpFont();
  2113.  
  2114.     if (fNumOfRows > 0)
  2115.         if (this->GetRowHeight(1) == 0)            // set row height from font 
  2116.             this->SetRowHeight(1, fNumOfRows, fLineHeight + fRowInset);
  2117.  
  2118.     if ((fNumOfCols == 1) && (fSizeDeterminer[hSel] != sizeFixed) && (this->GetColWidth(1) == 0))
  2119.         this->SetColWidth(1, fNumOfCols, (short)fSize.h);//!!! Note cast
  2120.  
  2121.     OffsetPtrWStr(itsParams, sizeof(TextGridViewTemplate));
  2122. }
  2123.  
  2124. //--------------------------------------------------------------------------------------------------
  2125. #pragma segment GVRes
  2126.  
  2127. pascal TObject* TTextGridView::Clone(void)        // override 
  2128. {
  2129.     TTextGridView * aClonedTextGridView = (TTextGridView *)(inherited::Clone());
  2130.  
  2131.     return aClonedTextGridView;
  2132. }
  2133.  
  2134. //--------------------------------------------------------------------------------------------------
  2135. #pragma segment GVNonRes
  2136.  
  2137. pascal void TTextGridView::WRes(ViewRsrcHandle theResource,
  2138.                                 Ptr& itsParams)    // override 
  2139. {
  2140.     short theSize;
  2141.     Str255 theFont;
  2142.  
  2143.     inherited::WRes(theResource, itsParams);
  2144.  
  2145.     theSize = fTextStyle.tsSize;
  2146.     GetPortFontInfo(fTextStyle.tsFont, theFont, theSize);
  2147.  
  2148.     TextGridViewTemplate& templateData = *((TextGridViewTemplate *) ExpandPtrWStr((Handle)theResource, itsParams, sizeof(TextGridViewTemplate), theFont.Length()));
  2149.     templateData.itsFontFace = fTextStyle.tsFace;
  2150.     templateData.itsFontSize = theSize;
  2151.     templateData.itsFontColor = fTextStyle.tsColor;
  2152.  
  2153.     // templateData.itsFontName = theFont; 
  2154.     CopyStr255(theFont, PRStr(templateData.itsFontName));
  2155. }
  2156.  
  2157. //--------------------------------------------------------------------------------------------------
  2158. #pragma segment GVNonRes
  2159.  
  2160. pascal void TTextGridView::WriteRes(ViewRsrcHandle theResource,
  2161.                                     Ptr& itsParams)// override 
  2162. {
  2163.     gWResSignature = 'txtg';
  2164.     gWResType = "TTextGridView";
  2165.     this->WRes(theResource, itsParams);
  2166. }
  2167.  
  2168. //--------------------------------------------------------------------------------------------------
  2169. #pragma segment GVRes
  2170.  
  2171. pascal void TTextGridView::DrawCell(GridCell aCell,
  2172.                                     const VRect& aRect)// override 
  2173. {
  2174.     Str255 theText;
  2175.     Rect r;
  2176.  
  2177.     this->GetText(aCell, theText);
  2178.  
  2179.     if (this->GetColWidth(aCell.h) > 0)
  2180.     {
  2181.         this->ViewToQDRect(aRect, r);
  2182.         MADrawString(theText, r, teFlushDefault);
  2183.     }
  2184. }
  2185.  
  2186. //--------------------------------------------------------------------------------------------------
  2187. #pragma segment GVRes
  2188.  
  2189. pascal Boolean TTextGridView::Focus(void)        // override 
  2190. {
  2191.     if (inherited::Focus())
  2192.     {
  2193.         this->SetPen();
  2194.         return TRUE;
  2195.     }
  2196.     else
  2197.         return FALSE;
  2198. }
  2199.  
  2200. //--------------------------------------------------------------------------------------------------
  2201. #pragma segment GVOpen
  2202.  
  2203. pascal void TTextGridView::SetUpFont(void)
  2204. {
  2205.     GrafPtr savedPort;
  2206.     FontInfo theFontInfo;
  2207.  
  2208.     GetPort(savedPort);
  2209.     SetPort(gWorkPort);
  2210.  
  2211.     this->SetPen();
  2212.     fLineHeight = MAGetFontInfo(theFontInfo);    // returns height of font 
  2213.     fLineAscent = theFontInfo.ascent + (theFontInfo.leading / 2);
  2214.  
  2215.     SetPort(savedPort);
  2216. }
  2217.  
  2218. //--------------------------------------------------------------------------------------------------
  2219. #pragma segment GVRes
  2220.  
  2221. pascal void TTextGridView::SetPen(void)
  2222. {
  2223.     TextStyle itsTextStyle = fTextStyle;
  2224.     SetPortTextStyle(itsTextStyle);
  2225.     PenNormal();
  2226. }
  2227.  
  2228. //--------------------------------------------------------------------------------------------------
  2229. #pragma segment GVRes
  2230.  
  2231. pascal void TTextGridView::GetText(GridCell        /* aCell */,
  2232.                                    Str255&        /* aString */)
  2233. {
  2234.     this->SubClassResponsibility();
  2235. }
  2236.  
  2237. //--------------------------------------------------------------------------------------------------
  2238. #pragma segment GVFields
  2239.  
  2240. pascal void TTextGridView::Fields(TObject* obj)    // override 
  2241. {
  2242.     obj->DoToField("TTextGridView", NULL, bClass);
  2243.     obj->DoToField("fLineHeight", &fLineHeight, bInteger);
  2244.     obj->DoToField("fLineAscent", &fLineAscent, bInteger);
  2245.     obj->DoToField("fTextStyle", &fTextStyle, bTextStyle);
  2246.  
  2247.     inherited::Fields(obj);
  2248. }
  2249.  
  2250. //--------------------------------------------------------------------------------------------------
  2251. #pragma segment GVOpen
  2252.  
  2253. pascal void TTextListView::Initialize(void)        // override 
  2254. {
  2255.     inherited::Initialize();
  2256. }
  2257.  
  2258. //--------------------------------------------------------------------------------------------------
  2259. #pragma segment GVOpen
  2260.  
  2261. pascal void TTextListView::ITextListView(TDocument* itsDocument,
  2262.                                          // Its document 
  2263.                                          TView* itsSuperView,
  2264.                                          // Its parent view 
  2265.                                          const VPoint& itsLocation,
  2266.                                          // Top, Left in parent's coords 
  2267.                                          const VPoint& itsSize,
  2268.                                          SizeDeterminer itsHSizeDet,
  2269.                                          SizeDeterminer itsVSizeDet,
  2270.                                          // Size determiners 
  2271.                                          short numOfItems,
  2272.                                          // Number of items initially 
  2273.                                          short rowHeight,
  2274.                                          // Row height, or zero for font height 
  2275.                                          short colWidth,
  2276.                                          // Width of items in the columns 
  2277.                                          Boolean adornRows,
  2278.                                          // Draw the row adornments? 
  2279.                                          Boolean adornCols,
  2280.                                          // Draw the col adornment? 
  2281.                                          short rowInset,
  2282.                                          // Amount to inset the rows 
  2283.                                          short colInset,
  2284.                                          // Amount to inset the column 
  2285.                                          Boolean singleSelection,
  2286.                                          // single cell selection? 
  2287.                                          const TextStyle& itsTextStyle)// size, color, etc. font info 
  2288.  
  2289. {
  2290.     this->ITextGridView(itsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet, numOfItems, 1, rowHeight, colWidth, adornRows, adornCols, rowInset, colInset, singleSelection, itsTextStyle);
  2291. }
  2292.  
  2293. //--------------------------------------------------------------------------------------------------
  2294. #pragma segment GVRes
  2295.  
  2296. pascal TObject* TTextListView::Clone(void)        // override 
  2297. {
  2298.     TTextListView * aClonedTextListView = (TTextListView *)(inherited::Clone());
  2299.  
  2300.     return aClonedTextListView;
  2301. }
  2302.  
  2303. //--------------------------------------------------------------------------------------------------
  2304. #pragma segment GVNonRes
  2305.  
  2306. pascal void TTextListView::WriteRes(ViewRsrcHandle theResource,
  2307.                                     Ptr& itsParams)// override 
  2308. {
  2309.     gWResSignature = 'lstg';
  2310.     gWResType = "TTextListView";
  2311.     this->WRes(theResource, itsParams);
  2312. }
  2313.  
  2314. //--------------------------------------------------------------------------------------------------
  2315. #pragma segment GVRes
  2316.  
  2317. pascal void TTextListView::AllItemsDo(pascal void(* DoToItem)(short anItem,
  2318.                                                               void* staticLink),
  2319.                                       void* staticLink)
  2320. {
  2321.     this->EachItemDo(1, fNumOfRows, DoToItem, staticLink);
  2322. }
  2323.  
  2324. //--------------------------------------------------------------------------------------------------
  2325. #pragma segment GVRes
  2326.  
  2327. pascal Boolean TTextListView::CanSelectCell(GridCell aCell)// override 
  2328. {
  2329.     return (inherited::CanSelectCell(aCell) && this->CanSelectItem(aCell.v));
  2330. }
  2331.  
  2332. //--------------------------------------------------------------------------------------------------
  2333. #pragma segment GVRes
  2334.  
  2335. pascal Boolean TTextListView::CanSelectItem(short anItem)
  2336. {
  2337.     return ((anItem >= 1) && (anItem <= fNumOfRows));
  2338. }
  2339.  
  2340. //--------------------------------------------------------------------------------------------------
  2341. #pragma segment GVNonRes
  2342.  
  2343. pascal void TTextListView::DelItemAt(short anItem,
  2344.                                      short numOfItems)
  2345. {
  2346.     this->DelRowAt(anItem, numOfItems);
  2347. }
  2348.  
  2349. //--------------------------------------------------------------------------------------------------
  2350. #pragma segment GVNonRes
  2351.  
  2352. pascal void TTextListView::DelItemFirst(short numOfItems)
  2353. {
  2354.     this->DelItemAt(1, numOfItems);
  2355. }
  2356.  
  2357. //--------------------------------------------------------------------------------------------------
  2358. #pragma segment GVNonRes
  2359.  
  2360. pascal void TTextListView::DelItemLast(short numOfItems)
  2361. {
  2362.     this->DelItemAt(fNumOfRows - numOfItems + 1, numOfItems);
  2363. }
  2364.  
  2365. //--------------------------------------------------------------------------------------------------
  2366. #pragma segment GVRes
  2367.  
  2368. pascal void TTextListView::EachItemDo(short start,
  2369.                                       short stop,
  2370.                                       pascal void(* DoToItem)(short anItem,
  2371.                                                               void* staticLink),
  2372.                                       void* staticLink)
  2373. {
  2374.     for (short i = start; i <= stop; ++i)
  2375.         DoToItem(i, staticLink);
  2376. }
  2377.  
  2378. //--------------------------------------------------------------------------------------------------
  2379. #pragma segment GVRes
  2380.  
  2381. // Iteration class to replace nested routine
  2382.  
  2383. class CDoToCell
  2384. {
  2385.     const DoToItemType& fDoToItem;
  2386.     const void*& fStaticLink;
  2387. public:
  2388.     // Constructor
  2389.     CDoToCell(const DoToItemType& DoToItem,
  2390.               const void*& staticLink) :
  2391.         fDoToItem(DoToItem),
  2392.         fStaticLink(staticLink)
  2393.     {
  2394.     }
  2395.  
  2396.     pascal void DoToCell(GridCell aCell);
  2397. };
  2398.  
  2399. #pragma segment GVRes
  2400. pascal void CDoToCell::DoToCell(GridCell aCell)
  2401. {
  2402.     fDoToItem(aCell.v, fStaticLink);
  2403. }
  2404.  
  2405. #pragma segment GVRes
  2406. pascal void TTextListView::EachSelectedItemDo(DoToItemType DoToItem,
  2407.                                               void* staticLink)
  2408.  
  2409. {
  2410.     CDoToCell aCDoToCell(DoToItem, staticLink);
  2411.  
  2412.     this->EachInRgn(fSelections, (DoToCellType) & CDoToCell::DoToCell, &aCDoToCell);
  2413. }
  2414.  
  2415. //--------------------------------------------------------------------------------------------------
  2416. #pragma segment GVRes
  2417.  
  2418. pascal short TTextListView::FirstSelectedItem(void)
  2419. {
  2420.     GridCell aGridCell(this->FirstSelectedCell());
  2421.     return aGridCell.v;
  2422. }
  2423.  
  2424. //--------------------------------------------------------------------------------------------------
  2425. #pragma segment GVRes
  2426.  
  2427. pascal short TTextListView::GetItemHeight(short anItem)
  2428. {
  2429.     return this->GetRowHeight(anItem);
  2430. }
  2431.  
  2432. //--------------------------------------------------------------------------------------------------
  2433. #pragma segment GVRes
  2434.  
  2435. pascal short TTextListView::GetItemWidth(void)
  2436. {
  2437.     return this->GetColWidth(1);
  2438. }
  2439.  
  2440. //--------------------------------------------------------------------------------------------------
  2441. #pragma segment GVRes
  2442.  
  2443. pascal void TTextListView::GetItemText(short    /* anItem */,
  2444.                                        Str255&    /* aString */)
  2445. {
  2446.     this->SubClassResponsibility();
  2447. }
  2448.  
  2449. //--------------------------------------------------------------------------------------------------
  2450. #pragma segment GVRes
  2451.  
  2452. pascal void TTextListView::GetText(GridCell aCell,
  2453.                                    Str255& aString)// override 
  2454. {
  2455.     this->GetItemText(aCell.v, aString);
  2456. }
  2457.  
  2458. //--------------------------------------------------------------------------------------------------
  2459. #pragma segment GVRes
  2460.  
  2461. pascal void TTextListView::InsItemBefore(short anItem,
  2462.                                          short numOfItems)
  2463. {
  2464.     this->InsRowBefore(anItem, numOfItems, fLineHeight + fRowInset);
  2465. }
  2466.  
  2467. //--------------------------------------------------------------------------------------------------
  2468. #pragma segment GVRes
  2469.  
  2470. pascal void TTextListView::InsItemFirst(short numOfItems)
  2471. {
  2472.     this->InsItemBefore(1, numOfItems);
  2473. }
  2474.  
  2475. //--------------------------------------------------------------------------------------------------
  2476. #pragma segment GVRes
  2477.  
  2478. pascal void TTextListView::InsItemLast(short numOfItems)
  2479. {
  2480.     this->InsItemBefore(fNumOfRows + 1, numOfItems);
  2481. }
  2482.  
  2483. //--------------------------------------------------------------------------------------------------
  2484. #pragma segment GVRes
  2485.  
  2486. pascal void TTextListView::InvalidateItem(short anItem)
  2487. {
  2488.     GridCell aCell(anItem, 1);
  2489.     this->InvalidateCell(aCell);
  2490. }
  2491.  
  2492. //--------------------------------------------------------------------------------------------------
  2493. #pragma segment GVRes
  2494.  
  2495. pascal Boolean TTextListView::IsItemSelected(short anItem)
  2496. {
  2497.     GridCell aCell(anItem, 1);
  2498.     return this->IsCellSelected(aCell);
  2499. }
  2500.  
  2501. //--------------------------------------------------------------------------------------------------
  2502. #pragma segment GVRes
  2503.  
  2504. pascal short TTextListView::LastSelectedItem(void)
  2505. {
  2506.     GridCell aGridCell(this->LastSelectedCell());
  2507.     return aGridCell.v;
  2508. }
  2509.  
  2510. //--------------------------------------------------------------------------------------------------
  2511. #pragma segment GVNonRes
  2512.  
  2513. pascal void TTextListView::Resize(const VPoint& newSize,
  2514.                                   Boolean invalidate)// override 
  2515. {
  2516.     inherited::Resize(newSize, invalidate);
  2517.  
  2518.     if (fNumOfCols == 1)
  2519.     {
  2520.         fColWidths->fTotal = fColWidths->fTotal - (*(fColWidths->fChunks))[0].value + newSize.h;
  2521.         (*(fColWidths->fChunks))[0].value = (short)newSize.h;//!!! Note cast
  2522.     }
  2523. }
  2524.  
  2525. //--------------------------------------------------------------------------------------------------
  2526. #pragma segment GVRes
  2527.  
  2528. pascal void TTextListView::SelectCell(GridCell theCell,
  2529.                                       Boolean extendSelection,
  2530.                                       Boolean highlight,
  2531.                                       Boolean select)// override 
  2532. {
  2533.     this->SelectItem(theCell.v, extendSelection, highlight, select);
  2534. }
  2535.  
  2536. //--------------------------------------------------------------------------------------------------
  2537. #pragma segment GVRes
  2538.  
  2539. pascal void TTextListView::SelectItem(short anItem,
  2540.                                       Boolean extendSelection,
  2541.                                       Boolean highlight,
  2542.                                       Boolean select)
  2543. {
  2544.     GridCell aCell(anItem, (short)Min(1, anItem));
  2545.  
  2546.     inherited::SelectCell(aCell, extendSelection, highlight, select);
  2547. }
  2548.  
  2549. //--------------------------------------------------------------------------------------------------
  2550. #pragma segment GVNonRes
  2551.  
  2552. pascal void TTextListView::SetItemHeight(short anItem,
  2553.                                          short numOfItems,
  2554.                                          short aHeight)
  2555. {
  2556.     this->SetRowHeight(anItem, numOfItems, aHeight);
  2557. }
  2558.  
  2559. //--------------------------------------------------------------------------------------------------
  2560. #pragma segment GVNonRes
  2561.  
  2562. pascal void TTextListView::SetItemWidth(short aWidth)
  2563. {
  2564.     this->SetColWidth(1, 1, aWidth);
  2565. }
  2566.  
  2567. //--------------------------------------------------------------------------------------------------
  2568. #pragma segment GVFields
  2569.  
  2570. pascal void TTextListView::Fields(TObject* obj)    // override 
  2571. {
  2572.     obj->DoToField("TTextListView", (Ptr)NULL, bClass);
  2573.  
  2574.     inherited::Fields(obj);
  2575. }
  2576.  
  2577. //--------------------------------------------------------------------------------------------------
  2578. #pragma segment GVSelCommand
  2579. pascal void TCellSelectCommand::Initialize(void)// override 
  2580. {
  2581.     inherited::Initialize();
  2582.     fAnchorCell = gZeroPt;                        // At least set it to something 
  2583.     fCmdKey = FALSE;
  2584.     fDeselecting = FALSE;
  2585.     fDifference = NULL;
  2586.     fGridView = NULL;
  2587.     fPrevCell = Point(-1, -1);
  2588.     fPrevSelection = NULL;
  2589.     fShiftKey = FALSE;
  2590.     fThisSelection = NULL;
  2591. }
  2592.  
  2593. //--------------------------------------------------------------------------------------------------
  2594. #pragma segment GVSelCommand
  2595.  
  2596. pascal void TCellSelectCommand::ICellSelectCommand(TGridView* itsView,
  2597.                                                    const VPoint& itsMouse,
  2598.                                                    Boolean theShiftKey,
  2599.                                                    Boolean theCmdKey)
  2600. {
  2601.     FailInfo fi;
  2602.  
  2603.     this->INoChangesTracker(cNoCommand, NULL, itsView, itsView->GetScroller(FALSE), itsMouse);
  2604.     fShiftKey = theShiftKey;
  2605.     fCmdKey = theCmdKey;
  2606.     fViewConstrain = FALSE;
  2607.  
  2608.     fGridView = itsView;
  2609.  
  2610.     if (fi.Try())
  2611.     {
  2612.         fPrevSelection = MakeNewRgn();
  2613.         CopyRgn(fGridView->fSelections, fPrevSelection);
  2614.         fThisSelection = fGridView->fHLRegion;
  2615.         SetEmptyRgn(fThisSelection);
  2616.         fDifference = MakeNewRgn();
  2617.         fi.Success();
  2618.     }
  2619.     else    // Recover
  2620.     {
  2621.         this->Free();
  2622.         fi.ReSignal();
  2623.     }
  2624. }
  2625.  
  2626. //--------------------------------------------------------------------------------------------------
  2627. #pragma segment GVDoCommand
  2628.  
  2629. pascal void TCellSelectCommand::Free(void)        // override 
  2630. {
  2631.     fPrevSelection = DisposeIfRgnHandle(fPrevSelection);
  2632.     fDifference = DisposeIfRgnHandle(fDifference);
  2633.  
  2634.     fThisSelection = NULL;                        /* I don't own it so I don't dispose it. But,
  2635.                                                   I sure don't need a reference to it any
  2636.                                                   more. */
  2637.  
  2638.     inherited::Free();
  2639. }
  2640.  
  2641. //--------------------------------------------------------------------------------------------------
  2642. #pragma segment GVDoCommand
  2643.  
  2644. pascal void TCellSelectCommand::ComputeAnchorCell(GridCell& clickedCell)
  2645. {
  2646.     fAnchorCell = clickedCell;
  2647.  
  2648.     if (fShiftKey && (!EmptyRgn(fPrevSelection)))
  2649.     {
  2650.         Rect & bounds = (**fPrevSelection).rgnBBox;
  2651.  
  2652.         if (fAnchorCell.h >= bounds.left)
  2653.             fAnchorCell.h = bounds.left;
  2654.         else
  2655.             fAnchorCell.h = bounds.right - 1;
  2656.         if (fAnchorCell.v >= bounds.top)
  2657.             fAnchorCell.v = bounds.top;
  2658.         else
  2659.             fAnchorCell.v = bounds.bottom - 1;
  2660.     }
  2661. }
  2662.  
  2663. //--------------------------------------------------------------------------------------------------
  2664. #pragma segment GVDoCommand
  2665.  
  2666. pascal void TCellSelectCommand::ComputeNewSelection(GridCell& clickedCell)
  2667. {
  2668.     Rect r;
  2669.  
  2670.     if (fGridView->CanSelectCell(clickedCell))
  2671.     {
  2672.         if (fGridView->fSingleSelection || (!fShiftKey))
  2673.             SetRect(r, clickedCell.h, clickedCell.v, clickedCell.h + 1, clickedCell.v + 1);
  2674.         else
  2675.         {
  2676.             Pt2Rect(fAnchorCell, clickedCell, r);
  2677.             ++r.right;
  2678.             ++r.bottom;
  2679.         }
  2680.         RectRgn(fThisSelection, r);
  2681.         if (fCmdKey && (!fGridView->fSingleSelection))
  2682.             if (fDeselecting)
  2683.                 DiffRgn(fPrevSelection, fThisSelection, fThisSelection);
  2684.             else
  2685.                 UnionRgn(fPrevSelection, fThisSelection, fThisSelection);
  2686.     }
  2687. }
  2688.  
  2689. //--------------------------------------------------------------------------------------------------
  2690. #pragma segment GVDoCommand
  2691.  
  2692. pascal void TCellSelectCommand::HighlightNewSelection(void)
  2693. {
  2694.     // Turn off previously selected cells 
  2695.     DiffRgn(fPrevSelection, fThisSelection, fDifference);
  2696.     fGridView->HighlightCells(fDifference, fGridView->fHLDesired, hlOff);
  2697.  
  2698.     // Turn on newly selected cells
  2699.     DiffRgn(fThisSelection, fPrevSelection, fDifference);
  2700.     fGridView->HighlightCells(fDifference, hlOff, fGridView->fHLDesired);
  2701. }
  2702.  
  2703. //--------------------------------------------------------------------------------------------------
  2704. #pragma segment GVDoCommand
  2705.  
  2706. pascal void TCellSelectCommand::TrackFeedback(TrackPhase /* aTrackPhase */,
  2707.                                               const VPoint& /* anchorPoint */,
  2708.                                               const VPoint& /* previousPoint */,
  2709.                                               const VPoint& /* nextPoint */,
  2710.                                               Boolean /* mouseDidMove */,
  2711.                                               Boolean /* turnItOn */)// override 
  2712. {
  2713. }
  2714.  
  2715. //--------------------------------------------------------------------------------------------------
  2716. #pragma segment GVDoCommand
  2717.  
  2718. pascal TTracker* TCellSelectCommand::TrackMouse(TrackPhase aTrackPhase,
  2719.                                                 VPoint&/* anchorPoint */ ,
  2720.                                                 VPoint&/* previousPoint */ ,
  2721.                                                 VPoint& nextPoint,
  2722.                                                 Boolean mouseDidMove)// override 
  2723. {
  2724.     GridCell clickedCell;
  2725.     VRect viewExtent;
  2726.     VPoint clippedPoint;
  2727.  
  2728.     if (mouseDidMove)
  2729.     {
  2730.         fGridView->GetExtent(viewExtent);
  2731.         clippedPoint = nextPoint;
  2732.         clippedPoint.ConstrainTo(viewExtent);
  2733.         clickedCell = fGridView->VPointToCell(clippedPoint);
  2734.         if (aTrackPhase == trackBegin)
  2735.         {
  2736.             this->ComputeAnchorCell(clickedCell);
  2737.             if (fCmdKey)
  2738.                 fDeselecting = PtInRgn(fAnchorCell, fGridView->fSelections);
  2739.         }
  2740.  
  2741.         if (clickedCell != fPrevCell)
  2742.         {
  2743.             this->ComputeNewSelection(clickedCell);
  2744.             this->HighlightNewSelection();
  2745.  
  2746.             CopyRgn(fThisSelection, fPrevSelection);
  2747.             fPrevCell = clickedCell;
  2748.         }
  2749.     }
  2750.     return this;
  2751. }
  2752.  
  2753. //--------------------------------------------------------------------------------------------------
  2754. #pragma segment GVDoCommand
  2755.  
  2756. pascal void TCellSelectCommand::DoIt(void)        // override 
  2757. {
  2758.     if (fGridView->fSingleSelection)
  2759.         fGridView->SelectCell((*fThisSelection)->rgnBBox[topLeft], kDontExtend, kDontHighlight, kSelect);
  2760.     else
  2761.         fGridView->SetSelection(fThisSelection, kDontExtend, kDontHighlight, kSelect);
  2762. }
  2763.  
  2764. //--------------------------------------------------------------------------------------------------
  2765. #pragma segment GVFields
  2766.  
  2767. pascal void TCellSelectCommand::Fields(TObject* obj)// override 
  2768. {
  2769.     obj->DoToField("TCellSelectCommand", NULL, bClass);
  2770.     obj->DoToField("fGridView", &fGridView, bObject);
  2771.     obj->DoToField("fShiftKey", &fShiftKey, bBoolean);
  2772.     obj->DoToField("fCmdKey", &fCmdKey, bBoolean);
  2773.     obj->DoToField("fDeselecting", &fDeselecting, bBoolean);
  2774.     obj->DoToField("fAnchorCell", &fAnchorCell, bPoint);
  2775.     obj->DoToField("fPrevCell", &fPrevCell, bPoint);
  2776.     obj->DoToField("fThisSelection", &fThisSelection, bRgnHandle);
  2777.     obj->DoToField("fPrevSelection", &fPrevSelection, bRgnHandle);
  2778.     obj->DoToField("fDifference", &fDifference, bRgnHandle);
  2779.  
  2780.     inherited::Fields(obj);
  2781. }
  2782.  
  2783. //--------------------------------------------------------------------------------------------------
  2784. #pragma segment GVDoCommand
  2785.  
  2786. pascal void TRCSelectCommand::ComputeNewSelection(GridCell& clickedCell)// override 
  2787. {
  2788.     Rect r;
  2789.  
  2790.  
  2791.     if (fGridView->CanSelectCell(clickedCell))
  2792.     {
  2793.         if (fGridView->fSingleSelection)
  2794.             r = Rect(clickedCell.v, clickedCell.h, clickedCell.v + 1, clickedCell.h + 1);
  2795.         else
  2796.         {
  2797.             Pt2Rect(fAnchorCell, clickedCell, r);
  2798.             ++r.right;
  2799.             ++r.bottom;
  2800.         }
  2801.         RectRgn(fThisSelection, r);
  2802.         if (fCmdKey && (!fGridView->fSingleSelection))
  2803.             if (fDeselecting)
  2804.                 DiffRgn(fPrevSelection, fThisSelection, fThisSelection);
  2805.             else
  2806.                 UnionRgn(fPrevSelection, fThisSelection, fThisSelection);
  2807.     }
  2808. }
  2809.  
  2810. //--------------------------------------------------------------------------------------------------
  2811. #pragma segment GVDoCommand
  2812.  
  2813. pascal TTracker* TRCSelectCommand::TrackMouse(TrackPhase aTrackPhase,
  2814.                                               VPoint&/* anchorPoint */ ,
  2815.                                               VPoint&/* previousPoint */ ,
  2816.                                               VPoint& nextPoint,
  2817.                                               Boolean mouseDidMove)// override 
  2818. {
  2819.     GridCell clickedCell;
  2820.     VRect viewExtent;
  2821.     VPoint clippedPoint;
  2822.  
  2823.     if (mouseDidMove)
  2824.     {
  2825.         fGridView->GetExtent(viewExtent);
  2826.         clippedPoint = nextPoint;
  2827.         clippedPoint.ConstrainTo(viewExtent);
  2828.         clickedCell = fGridView->VPointToCell(clippedPoint);
  2829.         if (aTrackPhase == trackBegin)
  2830.         {
  2831.             this->ComputeAnchorCell(clickedCell);
  2832.             if (fCmdKey)
  2833.                 fDeselecting = PtInRgn(fAnchorCell, fGridView->fSelections);
  2834.         }
  2835.  
  2836.         if (clickedCell != fPrevCell)
  2837.         {
  2838.             if (!fShiftKey && (aTrackPhase != trackBegin))
  2839.             {
  2840.                 this->ComputeAnchorCell(clickedCell);
  2841.                 if (fCmdKey)
  2842.                     fDeselecting = PtInRgn(fAnchorCell, fGridView->fSelections);
  2843.             }
  2844.             this->ComputeNewSelection(clickedCell);
  2845.             this->HighlightNewSelection();
  2846.  
  2847.             CopyRgn(fThisSelection, fPrevSelection);
  2848.             fPrevCell = clickedCell;
  2849.         }
  2850.     }
  2851.     return this;
  2852. }
  2853.  
  2854. //--------------------------------------------------------------------------------------------------
  2855. #pragma segment GVFields
  2856.  
  2857. pascal void TRCSelectCommand::Fields(TObject* obj)// override 
  2858. {
  2859.     obj->DoToField("TRCSelectCommand", (Ptr)NULL, bClass);
  2860.  
  2861.     inherited::Fields(obj);
  2862. }
  2863.  
  2864. //--------------------------------------------------------------------------------------------------
  2865. #pragma segment GVSelCommand
  2866.  
  2867. pascal void TRowSelectCommand::IRowSelectCommand(TGridView* itsView,
  2868.                                                  const VPoint& itsMouse,
  2869.                                                  Boolean theShiftKey,
  2870.                                                  Boolean theCmdKey)
  2871. {
  2872.     this->ICellSelectCommand(itsView, itsMouse, theShiftKey, theCmdKey);
  2873. }
  2874.  
  2875. //--------------------------------------------------------------------------------------------------
  2876. #pragma segment GVDoCommand
  2877.  
  2878. pascal void TRowSelectCommand::ComputeAnchorCell(GridCell& clickedCell)// override 
  2879. {
  2880.     inherited::ComputeAnchorCell(clickedCell);
  2881.     fAnchorCell.h = 1;
  2882. }
  2883.  
  2884. //--------------------------------------------------------------------------------------------------
  2885. #pragma segment GVDoCommand
  2886.  
  2887. pascal void TRowSelectCommand::ComputeNewSelection(GridCell& clickedCell)// override 
  2888. {
  2889.     clickedCell.h = fGridView->fNumOfCols;
  2890.  
  2891.     inherited::ComputeNewSelection(clickedCell);
  2892. }
  2893.  
  2894. //--------------------------------------------------------------------------------------------------
  2895. #pragma segment GVFields
  2896.  
  2897. pascal void TRowSelectCommand::Fields(TObject* obj)// override 
  2898. {
  2899.     obj->DoToField("TRowSelectCommand", (Ptr)NULL, bClass);
  2900.  
  2901.     inherited::Fields(obj);
  2902. }
  2903.  
  2904. //--------------------------------------------------------------------------------------------------
  2905. #pragma segment GVSelCommand
  2906.  
  2907. pascal void TColumnSelectCommand::IColumnSelectCommand(TGridView* itsView,
  2908.                                                        const VPoint& itsMouse,
  2909.                                                        Boolean theShiftKey,
  2910.                                                        Boolean theCmdKey)
  2911. {
  2912.     this->ICellSelectCommand(itsView, itsMouse, theShiftKey, theCmdKey);
  2913. }
  2914.  
  2915. //--------------------------------------------------------------------------------------------------
  2916. #pragma segment GVDoCommand
  2917.  
  2918. pascal void TColumnSelectCommand::ComputeAnchorCell(GridCell& clickedCell)// override 
  2919. {
  2920.     inherited::ComputeAnchorCell(clickedCell);
  2921.  
  2922.     fAnchorCell.v = 1;
  2923. }
  2924.  
  2925. //--------------------------------------------------------------------------------------------------
  2926. #pragma segment GVDoCommand
  2927.  
  2928. pascal void TColumnSelectCommand::ComputeNewSelection(GridCell& clickedCell)// override 
  2929. {
  2930.     clickedCell.v = fGridView->fNumOfRows;
  2931.  
  2932.     inherited::ComputeNewSelection(clickedCell);
  2933. }
  2934.  
  2935. //--------------------------------------------------------------------------------------------------
  2936. #pragma segment GVFields
  2937.  
  2938. pascal void TColumnSelectCommand::Fields(TObject* obj)// override 
  2939. {
  2940.     obj->DoToField("TColumnSelectCommand", (Ptr)NULL, bClass);
  2941.  
  2942.     inherited::Fields(obj);
  2943. }
  2944.  
  2945.  
  2946.